<commit_before>var meses = {
  Ene: 0,
  Feb: 1,
  Mar: 2,
  Abr: 3,
  May: 4,
  Jun: 5,
  Jul: 6,
  Ago: 7,
  Sep: 8,
  Oct: 9,
  Nov: 10,
  Dic: 11
};
var mesesNuevos = {
  "01-Ene-2015": 0,
  "01-Feb-2015": 1,
  "01-Mar-2015": 2,
  "01-Abr-2015": 3,
  "01-May-2015": 4,
  "01-Jun-2015": 5,
  "01-Jul-2015": 6,
  "01-Ago-2015": 7,
  "01-Sep-2015": 8,
  "01-Oct-2015": 9,
  "01-Nov-2015": 10,
  "01-Dic-2015": 11
};

/**
* Generates import/export graph from the specified path
* @param {string} container Container identifier
* @param {string} path Data source path
*/
function graphImportExport(container, path) {
  var width = $(container).width();
  var svg = d3.select(container).append('svg')
    .attr("width",width)
    .attr("height",350);

  var margin = {
      top: 20,
      right: 20,
      bottom: 30,
      left: 50
    },
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    g = svg
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var parseRow = function(d) {
    d.Mes = mesesNuevos[d.Mes];
    d.Importado = d.Importado;
    d.Exportado = d.Exportado;
    return d;
  };

  var xx = d3.scaleLinear().range([10, width]);
  var yy = d3.scaleLinear().range([height, 0]);

  var xaxis = d3
    .axisBottom(xx)
    .ticks(12)
    .tickFormat(function(d) {
      return Object.keys(meses)[d];
    });

  var lineImport = d3
    .line()
    .x(function(d) {
      return xx(d.Mes);
    })
    .y(function(d) {
      return yy(d.Importado);
    });

  var lineExport = d3
    .line()
    .x(function(d) {
      return xx(d.Mes);
    })
    .y(function(d) {
      return yy(d.Exportado);
    });

  d3.csv(path, parseRow, function(error, data) {
    mdata = data;
    if (error) {
      $(container).empty();
      $(container).append("Sin información");
      return;
    }
    maxImport = d3.max(data, function(d) {
      return parseInt(d.Importado);
    });
    maxExport = d3.max(data, function(d) {
      return parseInt(d.Exportado);
    });
    xx.domain([0, 11]);
    yy.domain([0, 1.1 * d3.max([maxImport, maxExport])]);

    g
      .append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(xaxis)
      .select(".domain")
      .remove();

    g
      .append("g")
      .call(d3.axisLeft(yy))
      .append("text") //texto
      .attr("fill", "#000")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("Toneladas");

    g
      .append("path")
      .data([data])
      .classed("line import", true)
      .transition()
      .attr("d", lineImport);

    g
      .append("path")
      .data([data])
      .classed("line export", true)
      .transition()
      .attr("d", lineExport);

    d3
      .selectAll("body")
      .append("div")
      .classed("d3-tooltip", true);

    g
      .append("text")
      .text("Importación")
      .attr("transform", function() {
        return "translate(" + (xx(data[11].Mes)) + "," + 18 + ")";
      })
      .classed("textImport", true)
      .style("text-anchor", "end" );

    var element = g
      .selectAll("circle.dotImport") //g1 is the update section
      .data(data)
      .enter()
      .append("circle")
      .classed("dotImport ", true)
      .attr("cx", function(d) {
        return xx(d.Mes);
      })
      .attr("cy", function(d) {
        return yy(d.Importado);
      })
      .attr("r", 0)
      .on("mouseover", function(d) {
        var mouse = d3.mouse(this);
        var absPositionSvg = $(".import-export>svg").position();
        $(".d3-tooltip").css("top", mouse[1] + absPositionSvg.top - 20 + "px");
        $(".d3-tooltip").css(
          "left",
          mouse[0] + absPositionSvg.left + 40 + "px"
        );
        $(".d3-tooltip").show();
        $(".d3-tooltip").html(d.Importado + " ton.");
      })
      .on("mouseout", function(d, i) {
        $(".d3-tooltip").hide();
        //    d3.select(this).select("circle")
      })
      .transition(300)
      .delay(500)
      .attr("r", 5);

    /*** export label **/
    g
      .append("text")
      .text("Exportación")
      .attr("transform", function() {
        return "translate(" + (xx(data[11].Mes)) + "," + 0 + ")";
      })
      .classed("textExport", true)
      .style("text-anchor", "end" );

    var element = g
      .selectAll("circle.dotExport") //g1 is the update section
      .data(data)
      .enter()
      .append("circle")
      .classed("dotExport ", true)
      .attr("cx", function(d) {
        return xx(d.Mes);
      })
      .attr("cy", function(d) {
        return yy(d.Exportado);
      })
      .attr("r", 0)
      .on("mouseover", function(d) {
        var mouse = d3.mouse(this);
        var absPositionSvg = $(".import-export>svg").position();
        $(".d3-tooltip").css("top", mouse[1] + absPositionSvg.top - 20 + "px");
        $(".d3-tooltip").css(
          "left",
          mouse[0] + absPositionSvg.left + 40 + "px"
        );
        $(".d3-tooltip").show();
        $(".d3-tooltip").html(d.Exportado + " ton.");
      })
      .on("mouseout", function(d, i) {
        $(".d3-tooltip").hide();
        //    d3.select(this).select("circle")
      })
      .transition(300)
      .delay(500)
      .attr("r", 5);
  });

}
/**
* Generates production graph from the specified path
*
* @param {string} container Container identifier
* @param {string} path Data source path
*/
function graphProduction(container, path) {
  var width = $(container).width();
  if (path === undefined) path = "data/grafico.csv";

  d3.csv(path, function(error, data) {
    if (error) {
      $(container).empty();
      $(container).append("Sin información");
      return;
    }

    var mdata = data;
    var numbers = [];
    mdata.forEach(function(el) {
      numbers.push(+el.Percent);
    });

    //data = data.slice(0, 3);

    var x = d3
      .scaleLinear()
      .domain([0, 100])
      .range([0, width - 10]);
    var colors = ["#A83232", "#C25C30", "#D98236", "#D9A036"];
    var enterSel = d3
      .select(container)
      .selectAll("div.bar-graph")
      .data(data)
      .enter()
      .append("div")
      .style("width", function(d) {
        return x(d.Percent) + "px";
      })
      .style("opacity", 0)
      .style("background-color", function(d, i) {
        return colors[i];
      })
      .classed("bar-graph", true);

    var enterSelText = d3
      .select(container)
      .selectAll("div.graph-text")
      .data(data)
      .enter()
      .append("div")
      .classed("graph-text", true)
      .style("width", function(d) {
        return x(d.Percent) + "px";
      })
      .style("opacity", 0);
    enterSelText
      .transition()
      .delay(1000)
      .style("opacity", 1);

    enterSelText.text(function(d) {
      return d.Provincia + " " + d.Percent + "%";
    });
    enterSelText.style("writing-mode", function(d) {
      if (x(d.Percent < 20)) return "vertical-rl";
      else "horizontal-tb";
    });
    enterSel
      .transition()
      .delay(0)
      .duration(1000)
      .delay(100)
      .style("opacity", 1);

  });
}

/**
* Generates the time of production graph
*
* @param {string} product Product name
* @param {string} container Graph container identifier
* @param {string} path Data source path
*/
function graphProductionTime(container){
  // Dimensions
  var contWidth = $(container).width(),
      margin = { top: 10, right: 10, bottom: 10, left: 5 },
      width = contWidth - margin.left - margin.right,
      height = 70 - margin.top - margin.bottom,
      months = $(container).data('time');

  // Initialize svg
  var svg = d3.select(container).selectAll('svg')
      .data([{}]).enter()
      .append('svg')
      .attr('width', width + margin.right + margin.left)
      .attr('height', height + margin.top + margin.bottom);

  // External group
  var chartWrapper = svg.selectAll('g.chartWrapper')
      .data([{}]).enter()
      .append('g')
      .attr('class', 'chartWrapper')
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  var xScale = d3.scaleBand()
    .domain(d3.range(12))
    .range([margin.left, width - margin.right])
    .padding(.3);

    months = months != 'NA' ? +months : 0;

    chartWrapper.selectAll('.time-line')
      .data(d3.range(12))
      .enter()
      .append('line')
      .attr('class', 'time-line')
      .classed('high', function(d, i) {
        return i < months ? true : false; })
      .attr('x1', function(d, i) { return xScale(i); })
      .attr('y1', height/2)
      .attr('x2', function(d, i) { return xScale(i) + xScale.bandwidth(); })
      .attr('y2', height/2)
      .style('stroke', function(d, i) { return i < months ? '#89BC10' : '#D8D8D8'; })
      .style('stroke-linecap', 'round')
      .style('stroke-width', 6);

    chartWrapper.selectAll('.time-line-label')
      .data([months])
      .enter()
      .append('text')
      .attr('x', xScale(0))
      .attr('y', height/2 + 30)
      .text(function(d) { if(d==0){ return "Sin información";}else{return d + ' meses';} })

}

/**
* Updates calendar bar in product page
* @param {string} product Product name
* @param {string} path Product's data path
*/
function updateCalendar(product, path) {
  $("#product-page li").removeClass(
    "in-season start-of-season out-of-season"
  );
  d3.csv(path + "/data/seasons/calendario.csv", function(calendar) {
    product = cleanLatin(product);
    for (var i = 0, id = 1; i < calendar.length; i++, id++) {
      if (calendar[i].PRODUCTO.toLowerCase() == product) {
        $("#product-page .month").each(function(index, item) {
          $item = $(item);
          switch (calendar[i][$item.data("month").toUpperCase()]) {
            case "Y":
              $item.closest("li").addClass("start-of-season");
              break;
            case "X":
              $item.closest("li").addClass("in-season");
              break;
          }
        });
        break;
      }
    }
  });
}

/**
* Helper function to the detect if the current element is overflown
* @param {object} element Element to be checked
* @return {boolean}
*/
function isOverflown(element) {
  return (
    element.scrollHeight > element.clientHeight ||
    element.scrollWidth > element.clientWidth
  );
}

/**
* Helper function to clear latin characters
* @param {string} src Source string
* @param {string}
*/
function cleanLatin(src) {
  src = src.replace("á", "a");
  src = src.replace("é", "e");
  src = src.replace("í", "i");
  src = src.replace("ó", "o");
  src = src.replace("ú", "u");
  src = src.replace("ñ", "n");
  return src;
}
<commit_msg>Se agregó el guión a cleanLatin<commit_after>var meses = {
  Ene: 0,
  Feb: 1,
  Mar: 2,
  Abr: 3,
  May: 4,
  Jun: 5,
  Jul: 6,
  Ago: 7,
  Sep: 8,
  Oct: 9,
  Nov: 10,
  Dic: 11
};
var mesesNuevos = {
  "01-Ene-2015": 0,
  "01-Feb-2015": 1,
  "01-Mar-2015": 2,
  "01-Abr-2015": 3,
  "01-May-2015": 4,
  "01-Jun-2015": 5,
  "01-Jul-2015": 6,
  "01-Ago-2015": 7,
  "01-Sep-2015": 8,
  "01-Oct-2015": 9,
  "01-Nov-2015": 10,
  "01-Dic-2015": 11
};

/**
* Generates import/export graph from the specified path
* @param {string} container Container identifier
* @param {string} path Data source path
*/
function graphImportExport(container, path) {
  var width = $(container).width();
  var svg = d3.select(container).append('svg')
    .attr("width",width)
    .attr("height",350);

  var margin = {
      top: 20,
      right: 20,
      bottom: 30,
      left: 50
    },
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    g = svg
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var parseRow = function(d) {
    d.Mes = mesesNuevos[d.Mes];
    d.Importado = d.Importado;
    d.Exportado = d.Exportado;
    return d;
  };

  var xx = d3.scaleLinear().range([10, width]);
  var yy = d3.scaleLinear().range([height, 0]);

  var xaxis = d3
    .axisBottom(xx)
    .ticks(12)
    .tickFormat(function(d) {
      return Object.keys(meses)[d];
    });

  var lineImport = d3
    .line()
    .x(function(d) {
      return xx(d.Mes);
    })
    .y(function(d) {
      return yy(d.Importado);
    });

  var lineExport = d3
    .line()
    .x(function(d) {
      return xx(d.Mes);
    })
    .y(function(d) {
      return yy(d.Exportado);
    });

  d3.csv(path, parseRow, function(error, data) {
    mdata = data;
    if (error) {
      $(container).empty();
      $(container).append("Sin información");
      return;
    }
    maxImport = d3.max(data, function(d) {
      return parseInt(d.Importado);
    });
    maxExport = d3.max(data, function(d) {
      return parseInt(d.Exportado);
    });
    xx.domain([0, 11]);
    yy.domain([0, 1.1 * d3.max([maxImport, maxExport])]);

    g
      .append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(xaxis)
      .select(".domain")
      .remove();

    g
      .append("g")
      .call(d3.axisLeft(yy))
      .append("text") //texto
      .attr("fill", "#000")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("Toneladas");

    g
      .append("path")
      .data([data])
      .classed("line import", true)
      .transition()
      .attr("d", lineImport);

    g
      .append("path")
      .data([data])
      .classed("line export", true)
      .transition()
      .attr("d", lineExport);

    d3
      .selectAll("body")
      .append("div")
      .classed("d3-tooltip", true);

    g
      .append("text")
      .text("Importación")
      .attr("transform", function() {
        return "translate(" + (xx(data[11].Mes)) + "," + 18 + ")";
      })
      .classed("textImport", true)
      .style("text-anchor", "end" );

    var element = g
      .selectAll("circle.dotImport") //g1 is the update section
      .data(data)
      .enter()
      .append("circle")
      .classed("dotImport ", true)
      .attr("cx", function(d) {
        return xx(d.Mes);
      })
      .attr("cy", function(d) {
        return yy(d.Importado);
      })
      .attr("r", 0)
      .on("mouseover", function(d) {
        var mouse = d3.mouse(this);
        var absPositionSvg = $(".import-export>svg").position();
        $(".d3-tooltip").css("top", mouse[1] + absPositionSvg.top - 20 + "px");
        $(".d3-tooltip").css(
          "left",
          mouse[0] + absPositionSvg.left + 40 + "px"
        );
        $(".d3-tooltip").show();
        $(".d3-tooltip").html(d.Importado + " ton.");
      })
      .on("mouseout", function(d, i) {
        $(".d3-tooltip").hide();
        //    d3.select(this).select("circle")
      })
      .transition(300)
      .delay(500)
      .attr("r", 5);

    /*** export label **/
    g
      .append("text")
      .text("Exportación")
      .attr("transform", function() {
        return "translate(" + (xx(data[11].Mes)) + "," + 0 + ")";
      })
      .classed("textExport", true)
      .style("text-anchor", "end" );

    var element = g
      .selectAll("circle.dotExport") //g1 is the update section
      .data(data)
      .enter()
      .append("circle")
      .classed("dotExport ", true)
      .attr("cx", function(d) {
        return xx(d.Mes);
      })
      .attr("cy", function(d) {
        return yy(d.Exportado);
      })
      .attr("r", 0)
      .on("mouseover", function(d) {
        var mouse = d3.mouse(this);
        var absPositionSvg = $(".import-export>svg").position();
        $(".d3-tooltip").css("top", mouse[1] + absPositionSvg.top - 20 + "px");
        $(".d3-tooltip").css(
          "left",
          mouse[0] + absPositionSvg.left + 40 + "px"
        );
        $(".d3-tooltip").show();
        $(".d3-tooltip").html(d.Exportado + " ton.");
      })
      .on("mouseout", function(d, i) {
        $(".d3-tooltip").hide();
        //    d3.select(this).select("circle")
      })
      .transition(300)
      .delay(500)
      .attr("r", 5);
  });

}
/**
* Generates production graph from the specified path
*
* @param {string} container Container identifier
* @param {string} path Data source path
*/
function graphProduction(container, path) {
  var width = $(container).width();
  if (path === undefined) path = "data/grafico.csv";

  d3.csv(path, function(error, data) {
    if (error) {
      $(container).empty();
      $(container).append("Sin información");
      return;
    }

    var mdata = data;
    var numbers = [];
    mdata.forEach(function(el) {
      numbers.push(+el.Percent);
    });

    //data = data.slice(0, 3);

    var x = d3
      .scaleLinear()
      .domain([0, 100])
      .range([0, width - 10]);
    var colors = ["#A83232", "#C25C30", "#D98236", "#D9A036"];
    var enterSel = d3
      .select(container)
      .selectAll("div.bar-graph")
      .data(data)
      .enter()
      .append("div")
      .style("width", function(d) {
        return x(d.Percent) + "px";
      })
      .style("opacity", 0)
      .style("background-color", function(d, i) {
        return colors[i];
      })
      .classed("bar-graph", true);

    var enterSelText = d3
      .select(container)
      .selectAll("div.graph-text")
      .data(data)
      .enter()
      .append("div")
      .classed("graph-text", true)
      .style("width", function(d) {
        return x(d.Percent) + "px";
      })
      .style("opacity", 0);
    enterSelText
      .transition()
      .delay(1000)
      .style("opacity", 1);

    enterSelText.text(function(d) {
      return d.Provincia + " " + d.Percent + "%";
    });
    enterSelText.style("writing-mode", function(d) {
      if (x(d.Percent < 20)) return "vertical-rl";
      else "horizontal-tb";
    });
    enterSel
      .transition()
      .delay(0)
      .duration(1000)
      .delay(100)
      .style("opacity", 1);

  });
}

/**
* Generates the time of production graph
*
* @param {string} product Product name
* @param {string} container Graph container identifier
* @param {string} path Data source path
*/
function graphProductionTime(container){
  // Dimensions
  var contWidth = $(container).width(),
      margin = { top: 10, right: 10, bottom: 10, left: 5 },
      width = contWidth - margin.left - margin.right,
      height = 70 - margin.top - margin.bottom,
      months = $(container).data('time');

  // Initialize svg
  var svg = d3.select(container).selectAll('svg')
      .data([{}]).enter()
      .append('svg')
      .attr('width', width + margin.right + margin.left)
      .attr('height', height + margin.top + margin.bottom);

  // External group
  var chartWrapper = svg.selectAll('g.chartWrapper')
      .data([{}]).enter()
      .append('g')
      .attr('class', 'chartWrapper')
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  var xScale = d3.scaleBand()
    .domain(d3.range(12))
    .range([margin.left, width - margin.right])
    .padding(.3);

    months = months != 'NA' ? +months : 0;

    chartWrapper.selectAll('.time-line')
      .data(d3.range(12))
      .enter()
      .append('line')
      .attr('class', 'time-line')
      .classed('high', function(d, i) {
        return i < months ? true : false; })
      .attr('x1', function(d, i) { return xScale(i); })
      .attr('y1', height/2)
      .attr('x2', function(d, i) { return xScale(i) + xScale.bandwidth(); })
      .attr('y2', height/2)
      .style('stroke', function(d, i) { return i < months ? '#89BC10' : '#D8D8D8'; })
      .style('stroke-linecap', 'round')
      .style('stroke-width', 6);

    chartWrapper.selectAll('.time-line-label')
      .data([months])
      .enter()
      .append('text')
      .attr('x', xScale(0))
      .attr('y', height/2 + 30)
      .text(function(d) { if(d==0){ return "Sin información";}else{return d + ' meses';} })

}

/**
* Updates calendar bar in product page
* @param {string} product Product name
* @param {string} path Product's data path
*/
function updateCalendar(product, path) {
  $("#product-page li").removeClass(
    "in-season start-of-season out-of-season"
  );
  d3.csv(path + "/data/seasons/calendario.csv", function(calendar) {
    product = cleanLatin(product);
    for (var i = 0, id = 1; i < calendar.length; i++, id++) {
      if (calendar[i].PRODUCTO.toLowerCase() == product) {
        $("#product-page .month").each(function(index, item) {
          $item = $(item);
          switch (calendar[i][$item.data("month").toUpperCase()]) {
            case "Y":
              $item.closest("li").addClass("start-of-season");
              break;
            case "X":
              $item.closest("li").addClass("in-season");
              break;
          }
        });
        break;
      }
    }
  });
}

/**
* Helper function to the detect if the current element is overflown
* @param {object} element Element to be checked
* @return {boolean}
*/
function isOverflown(element) {
  return (
    element.scrollHeight > element.clientHeight ||
    element.scrollWidth > element.clientWidth
  );
}

/**
* Helper function to clear latin characters
* @param {string} src Source string
* @param {string}
*/
function cleanLatin(src) {
  src = src.replace("á", "a");
  src = src.replace("é", "e");
  src = src.replace("í", "i");
  src = src.replace("ó", "o");
  src = src.replace("ú", "u");
  src = src.replace("ñ", "n");
  src = src.replace(/-/g, " ");
  return src;
}
<|endoftext|>


<commit_before>// initialize the local object for user data
function WkUserData() {
  this.userPublicKey = "";
  this.refreshInterval = 900000;
  this.notifLifetime = 10000;
  this.inAppNavigation = true;
  this.expandInfoPanel = true;
  this.hide0Badge = false;
  this.notifSound = false;

  this.username = "Mysterious Unknown";
  this.emailAddress = "";
  this.gravatar = "";
  this.level = "42";
  this.nbLessons = 0;
  this.nbReviews = 0;
  this.srsNbApprentice = 0;
  this.srsNbGuru = 0;
  this.srsNbMaster = 0;
  this.srsNbEnlighten = 0;
  this.srsNbBurned = 0;
  this.assignmentsLastModified = null;
  this.summaryLastModified = null;
}

// save the local user data
function setWkUserData(wkUserData, callback) {
  // save the data into the local storage
  localStorage.wkUserData = JSON.stringify(wkUserData);
  // ... and sync it with the current Chrome account
  chrome.storage.sync.set({ wkUserData: wkUserData });

  if (callback) callback();
}

// get the local user data as an object
function getWkUserData() {
  return JSON.parse(localStorage.wkUserData);
}

// get the user data via the WaniKani API
function getApiData(publicKey, type, callback) {
  var xhr = new XMLHttpRequest();

  const modifiedDate =
    type === "user"
      ? null
      : type === "summary"
      ? "summaryLastModified"
      : "assignmentsLastModified";
  xhr.open("GET", `https://api.wanikani.com/v2/${type}`, true);
  xhr.setRequestHeader("Authorization", `Bearer ${publicKey}`);
  xhr.setRequestHeader("Cache-Control", "no-cache");
  if (modifiedDate && JSON.parse(localStorage.wkUserData)[modifiedDate]) {
    xhr.setRequestHeader(
      "If-Modified-Since",
      moment(JSON.parse(localStorage.wkUserData)[modifiedDate]).format(
        "ddd, DD MMM YYYY HH:mm:ss [GMT]"
      )
    );
  }
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
      const response = xhr.responseText ? JSON.parse(xhr.responseText) : {};
      callback(response);
    }
  };
  xhr.send();
}

function fetchAssignmentsLoop(
  publicKey,
  callback,
  assignments = [],
  nextUrl = ""
) {
  getApiData(publicKey, `assignments?hidden=false${nextUrl}`, function (
    responseData
  ) {
    if (!responseData.data) return null;
    const nextAssignments = assignments.concat(responseData.data);
    if (responseData.pages.next_url) {
      const nextUrlId = responseData.data[responseData.data.length - 1].id;
      fetchAssignmentsLoop(
        publicKey,
        callback,
        nextAssignments,
        `&page_after_id=${nextUrlId}`
      );
    } else {
      const srsDistributionOfAssignments = {
        apprentice: 0,
        guru: 0,
        master: 0,
        enlighten: 0,
        burned: 0,
        assignmentsLastModified: responseData.data_updated_at,
      };
      nextAssignments.forEach(assignment => {
        const srsStage = assignment.data.srs_stage;
        if (srsStage > 0 && srsStage <= 4) {
          srsDistributionOfAssignments.apprentice += 1;
        } else if (srsStage > 4 && srsStage <= 6) {
          srsDistributionOfAssignments.guru += 1;
        } else if (srsStage == 7) {
          srsDistributionOfAssignments.master += 1;
        } else if (srsStage == 8) {
          srsDistributionOfAssignments.enlighten += 1;
        } else if (srsStage == 9) {
          srsDistributionOfAssignments.burned += 1;
        }
      });
      updateWkUserData(
        srsDistributionOfAssignments,
        "srs-distribution",
        function () {
          if (callback) callback();
        }
      );
      // return srsDistributionOfAssignments;
    }
  });
}

// get a human readable value of the remaning time before the [reviewDate]
function parseRemainingTime(reviewDate) {
  if (reviewDate) {
    var now = moment();
    var review = moment(reviewDate);
    return review.from(now);
  }
  // [reviewDate] is null when the user hasn't done any lesson yet
  return null;
}

// update the local user data from the JSON data returned from the WaniKani API
function updateWkUserData(jsonUserData, type, callback) {
  var wkUserData = JSON.parse(localStorage.wkUserData);

  if (type == "summary" && jsonUserData.data) {
    wkUserData.nbLessons = jsonUserData.data.lessons[0].subject_ids.length;
    const nextReviews = jsonUserData.data.reviews.find(
      rev => rev.subject_ids.length > 0
    );
    wkUserData.nbReviews = nextReviews ? nextReviews.subject_ids.length : 0;
    wkUserData.nextReview = parseRemainingTime(
      jsonUserData.data.next_reviews_at
    );
    wkUserData.summaryLastModified = jsonUserData.data_updated_at;
  } else if (type == "srs-distribution" && jsonUserData) {
    wkUserData.srsNbApprentice = jsonUserData.apprentice;
    wkUserData.srsNbGuru = jsonUserData.guru;
    wkUserData.srsNbMaster = jsonUserData.master;
    wkUserData.srsNbEnlighten = jsonUserData.enlighten;
    wkUserData.srsNbBurned = jsonUserData.burned;
    wkUserData.assignmentsLastModified = jsonUserData.assignmentsLastModified;
  }

  setWkUserData(wkUserData);

  if (callback) callback();
}

// request the data to Wanikani API, display notifications and save local data
function requestUserData(notify, callback) {
  var currentData = getWkUserData();
  // update data and display notifications
  if (currentData.userPublicKey != "") {
    // get lessons and reviews data
    getApiData(currentData.userPublicKey, "summary", function (userData) {
      const nextReviews = userData.data
        ? userData.data.reviews.find(rev => rev.subject_ids.length > 0)
        : null;
      var nbLessons = userData.data
        ? userData.data.lessons[0].subject_ids.length
        : currentData.nbLessons;
      var nbReviews = userData.data
        ? nextReviews
          ? nextReviews.subject_ids.length
          : 0
        : currentData.nbReviews;

      // display desktop notifications
      if (notify === true && currentData.refreshInterval != 0) {
        var notified = false;
        if (nbReviews > 0 && nbReviews != currentData.nbReviews) {
          createNotification(
            "You have " + nbReviews + " reviews available.",
            "https://www.wanikani.com/review",
            "reviews"
          );
          notified = true;
        }
        //if (nbLessons > 0 && nbLessons != currentData.nbLessons) {
        if (nbLessons > 0 && nbLessons != currentData.nbLessons) {
          createNotification(
            "You have " + nbLessons + " lessons available.",
            "https://www.wanikani.com/lesson",
            "lessons"
          );
          notified = true;
        }
        // play notification sound
        if (notified === true && currentData.notifSound === true) {
          var sound = new Audio("/snd/notification.mp3");
          sound.play();
        }
      }

      // update badge text and title
      var total = nbReviews + nbLessons;
      if (total == 0 && currentData.hide0Badge) {
        chrome.browserAction.setBadgeText({ text: "" });
      } else {
        chrome.browserAction.setBadgeText({ text: total.toString() });
      }
      chrome.browserAction.setTitle({
        title:
          "WaniKani Companion\n" +
          "Lesson(s): " +
          nbLessons +
          "\n" +
          "Review(s): " +
          nbReviews,
      });

      // save study data
      updateWkUserData(userData, "summary", function () {
        fetchAssignmentsLoop(currentData.userPublicKey, callback);
      });
    });
  }
}

// create a HTML notification
function createNotification(body, url, tag) {
  var notification = new Notification("WaniKani Companion", {
    icon: "/img/wanikani/icon.png",
    body: body,
    tag: tag,
  });

  notification.onclick = function () {
    window.open(url);
  };

  // vanish the notifications after [notifLifetime] ms
  // if [notifLifetime] == -1, the notification stay until the user close it
  if (getWkUserData().notifLifetime != -1) {
    notification.onshow = function () {
      window.setTimeout(function () {
        notification.close();
      }, getWkUserData().notifLifetime);
    };
  }
}
<commit_msg>Update helper.js<commit_after>// initialize the local object for user data
function WkUserData() {
  this.userPublicKey = "";
  this.refreshInterval = 900000;
  this.notifLifetime = 10000;
  this.inAppNavigation = true;
  this.expandInfoPanel = true;
  this.hide0Badge = false;
  this.notifSound = false;

  this.username = "Mysterious Unknown";
  this.emailAddress = "";
  this.gravatar = "";
  this.level = "42";
  this.nbLessons = 0;
  this.nbReviews = 0;
  this.srsNbApprentice = 0;
  this.srsNbGuru = 0;
  this.srsNbMaster = 0;
  this.srsNbEnlighten = 0;
  this.srsNbBurned = 0;
  this.assignmentsLastModified = null;
  this.summaryLastModified = null;
}

// save the local user data
function setWkUserData(wkUserData, callback) {
  // save the data into the local storage
  localStorage.wkUserData = JSON.stringify(wkUserData);
  // ... and sync it with the current Chrome account
  chrome.storage.sync.set({ wkUserData: wkUserData });

  if (callback) callback();
}

// get the local user data as an object
function getWkUserData() {
  return JSON.parse(localStorage.wkUserData);
}

// get the user data via the WaniKani API
function getApiData(publicKey, type, callback) {
  var xhr = new XMLHttpRequest();

  const modifiedDate =
    type === "user"
      ? null
      : type === "summary"
      ? "summaryLastModified"
      : "assignmentsLastModified";
  xhr.open("GET", `https://api.wanikani.com/v2/${type}`, true);
  xhr.setRequestHeader("Authorization", `Bearer ${publicKey}`);
  xhr.setRequestHeader("Cache-Control", "no-cache");
  if (modifiedDate && JSON.parse(localStorage.wkUserData)[modifiedDate]) {
    xhr.setRequestHeader(
      "If-Modified-Since",
      moment(JSON.parse(localStorage.wkUserData)[modifiedDate]).format(
        "ddd, DD MMM YYYY HH:mm:ss [GMT]"
      )
    );
  }
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
      const response = xhr.responseText ? JSON.parse(xhr.responseText) : {};
      callback(response);
    }
  };
  xhr.send();
}

function fetchAssignmentsLoop(
  publicKey,
  callback,
  assignments = [],
  nextUrl = ""
) {
  getApiData(publicKey, `assignments?hidden=false${nextUrl}`, function (
    responseData
  ) {
    if (!responseData.data) return null;
    const nextAssignments = assignments.concat(responseData.data);
    if (responseData.pages.next_url) {
      const nextUrlId = responseData.data[responseData.data.length - 1].id;
      fetchAssignmentsLoop(
        publicKey,
        callback,
        nextAssignments,
        `&page_after_id=${nextUrlId}`
      );
    } else {
      const srsDistributionOfAssignments = {
        apprentice: 0,
        guru: 0,
        master: 0,
        enlighten: 0,
        burned: 0,
        assignmentsLastModified: responseData.data_updated_at,
      };
      nextAssignments.forEach(assignment => {
        const srsStage = assignment.data.srs_stage;
        if (srsStage > 0 && srsStage <= 4) {
          srsDistributionOfAssignments.apprentice += 1;
        } else if (srsStage > 4 && srsStage <= 6) {
          srsDistributionOfAssignments.guru += 1;
        } else if (srsStage == 7) {
          srsDistributionOfAssignments.master += 1;
        } else if (srsStage == 8) {
          srsDistributionOfAssignments.enlighten += 1;
        } else if (srsStage == 9) {
          srsDistributionOfAssignments.burned += 1;
        }
      });
      updateWkUserData(
        srsDistributionOfAssignments,
        "srs-distribution",
        function () {
          if (callback) callback();
        }
      );
      // return srsDistributionOfAssignments;
    }
  });
}

// get a human readable value of the remaning time before the [reviewDate]
function parseRemainingTime(reviewDate) {
  if (reviewDate) {
    var now = moment();
    var review = moment(reviewDate);
    return review.from(now);
  }
  // [reviewDate] is null when the user hasn't done any lesson yet
  return null;
}

// update the local user data from the JSON data returned from the WaniKani API
function updateWkUserData(jsonUserData, type, callback) {
  var wkUserData = JSON.parse(localStorage.wkUserData);

  if (type == "summary" && jsonUserData.data) {
    wkUserData.nbLessons = jsonUserData.data.lessons[0].subject_ids.length;
    const nextReviews = jsonUserData.data.reviews.find(
      rev => rev.subject_ids.length > 0 && rev.available_at <= moment()
    );
    wkUserData.nbReviews = nextReviews ? nextReviews.subject_ids.length : 0;
    wkUserData.nextReview = parseRemainingTime(
      jsonUserData.data.next_reviews_at
    );
    wkUserData.summaryLastModified = jsonUserData.data_updated_at;
  } else if (type == "srs-distribution" && jsonUserData) {
    wkUserData.srsNbApprentice = jsonUserData.apprentice;
    wkUserData.srsNbGuru = jsonUserData.guru;
    wkUserData.srsNbMaster = jsonUserData.master;
    wkUserData.srsNbEnlighten = jsonUserData.enlighten;
    wkUserData.srsNbBurned = jsonUserData.burned;
    wkUserData.assignmentsLastModified = jsonUserData.assignmentsLastModified;
  }

  setWkUserData(wkUserData);

  if (callback) callback();
}

// request the data to Wanikani API, display notifications and save local data
function requestUserData(notify, callback) {
  var currentData = getWkUserData();
  // update data and display notifications
  if (currentData.userPublicKey != "") {
    // get lessons and reviews data
    getApiData(currentData.userPublicKey, "summary", function (userData) {
      const nextReviews = userData.data
        ? userData.data.reviews.find(rev => rev.subject_ids.length > 0 && rev.available_at <= moment())
        : null;
      var nbLessons = userData.data
        ? userData.data.lessons[0].subject_ids.length
        : currentData.nbLessons;
      var nbReviews = userData.data
        ? nextReviews
          ? nextReviews.subject_ids.length
          : 0
        : currentData.nbReviews;

      // display desktop notifications
      if (notify === true && currentData.refreshInterval != 0) {
        var notified = false;
        if (nbReviews > 0 && nbReviews != currentData.nbReviews) {
          createNotification(
            "You have " + nbReviews + " reviews available.",
            "https://www.wanikani.com/review",
            "reviews"
          );
          notified = true;
        }
        //if (nbLessons > 0 && nbLessons != currentData.nbLessons) {
        if (nbLessons > 0 && nbLessons != currentData.nbLessons) {
          createNotification(
            "You have " + nbLessons + " lessons available.",
            "https://www.wanikani.com/lesson",
            "lessons"
          );
          notified = true;
        }
        // play notification sound
        if (notified === true && currentData.notifSound === true) {
          var sound = new Audio("/snd/notification.mp3");
          sound.play();
        }
      }

      // update badge text and title
      var total = nbReviews + nbLessons;
      if (total == 0 && currentData.hide0Badge) {
        chrome.browserAction.setBadgeText({ text: "" });
      } else {
        chrome.browserAction.setBadgeText({ text: total.toString() });
      }
      chrome.browserAction.setTitle({
        title:
          "WaniKani Companion\n" +
          "Lesson(s): " +
          nbLessons +
          "\n" +
          "Review(s): " +
          nbReviews,
      });

      // save study data
      updateWkUserData(userData, "summary", function () {
        fetchAssignmentsLoop(currentData.userPublicKey, callback);
      });
    });
  }
}

// create a HTML notification
function createNotification(body, url, tag) {
  var notification = new Notification("WaniKani Companion", {
    icon: "/img/wanikani/icon.png",
    body: body,
    tag: tag,
  });

  notification.onclick = function () {
    window.open(url);
  };

  // vanish the notifications after [notifLifetime] ms
  // if [notifLifetime] == -1, the notification stay until the user close it
  if (getWkUserData().notifLifetime != -1) {
    notification.onshow = function () {
      window.setTimeout(function () {
        notification.close();
      }, getWkUserData().notifLifetime);
    };
  }
}
<|endoftext|>


<commit_before>/*

This file contains all of the code running in the background that makes resumeBuilder.js possible. We call these helper functions because they support your code in this course.

Don't worry, you'll learn what's going on in this file throughout the course. You won't need to make any changes to it until you start experimenting with inserting a Google Map in Problem Set 3.

Cameron Pittman
*/

/*
These are HTML strings. As part of the course, you'll be using JavaScript functions
replace the %data% placeholder text you see in them.
*/
var HTMLheaderName = '
%data%
';
var HTMLheaderRole = '%data%
';

var HTMLcontactGeneric = '
%contact%%data%
';
var HTMLmobile = '
mobile%data%
';
var HTMLemail = '
email%data%
';
var HTMLtwitter = '
twitter%data%
';
var HTMLgithub = '
github%data%
';
var HTMLblog = '
blog%data%
';
var HTMLlocation = '
location%data%
';

var HTMLbioPic = '';
var HTMLwelcomeMsg = '%data%';

var HTMLskillsStart = '
Skills at a Glance:

';
var HTMLskills = '
%data%
';

var HTMLworkStart = '

';
var HTMLworkEmployer = '%data%';
var HTMLworkTitle = ' - %data%';
var HTMLworkDates = '
%data%
';
var HTMLworkLocation = '
%data%
';
var HTMLworkDescription = '

%data%
';

var HTMLprojectStart = '

';
var HTMLprojectTitle = '%data%';
var HTMLprojectDates = '
%data%
';
var HTMLprojectDescription = '

%data%
';
var HTMLprojectImage = '';

var HTMLschoolStart = '

';
var HTMLschoolName = '%data%';
var HTMLschoolDegree = ' -- %data%';
var HTMLschoolDates = '
%data%
';
var HTMLschoolLocation = '
%data%
';
var HTMLschoolMajor = '
Major: %data%';

var HTMLonlineClasses = '
Online Classes
';
var HTMLonlineTitle = '%data%';
var HTMLonlineSchool = ' - %data%';
var HTMLonlineDates = '
%data%
';
var HTMLonlineURL = '
%data%';

var internationalizeButton = '<button>Internationalize</button>';
var googleMap = '

';

/*
The International Name challenge in Lesson 2 where you'll create a function that will need this helper code to run. Don't delete! It hooks up your code to the button you'll be appending.
*/
$(document).ready(function() {
  $('button').click(function() {
    var iName = inName() || function(){};
    $('#name').html(iName);
  });
});

/*
The next few lines about clicks are for the Collecting Click Locations quiz in Lesson 2.
*/
clickLocations = [];

function logClicks(x,y) {
  clickLocations.push(
    {
      x: x,
      y: y
    }
  );
  console.log('x location: ' + x + '; y location: ' + y);
}

$(document).click(function(loc) {
  // your code goes here!
});

/*
This is the fun part. Here's where we generate the custom Google Map for the website.
See the documentation below for more details.
https://developers.google.com/maps/documentation/javascript/reference
*/
var map;    // declares a global map variable

/*
Start here! initializeMap() is called when page is loaded.
*/
function initializeMap() {

  var locations;

  var mapOptions = {
    disableDefaultUI: true
  };

  /*
  For the map to be displayed, the googleMap var must be
  appended to #mapDiv in resumeBuilder.js.
  */
  map = new google.maps.Map(document.querySelector('#map'), mapOptions);

  /*
  locationFinder() returns an array of every location string from the JSONs
  written for bio, education, and work.
  */
  function locationFinder() {

    // initializes an empty array
    var locations = [];

    // adds the single location property from bio to the locations array
    locations.push(bio.contacts.location);

    // iterates through school locations and appends each location to
    // the locations array
    for (var school in education.schools) {
      locations.push(education.schools[school].location);
    }

    // iterates through work locations and appends each location to
    // the locations array
    for (var job in work.jobs) {
      locations.push(work.jobs[job].location);
    }

    return locations;
  }

  /*
  createMapMarker(placeData) reads Google Places search results to create map pins.
  placeData is the object returned from search results containing information
  about a single location.
  */
  function createMapMarker(placeData) {

    // The next lines save location data from the search result object to local variables
    var lat = placeData.geometry.location.lat();  // latitude from the place service
    var lon = placeData.geometry.location.lng();  // longitude from the place service
    var name = placeData.formatted_address;   // name of the place from the place service
    var bounds = window.mapBounds;            // current boundaries of the map window

    // marker is an object with additional data about the pin for a single location
    var marker = new google.maps.Marker({
      map: map,
      position: placeData.geometry.location,
      title: name
    });

    // infoWindows are the little helper windows that open when you click
    // or hover over a pin on a map. They usually contain more information
    // about a location.
    var infoWindow = new google.maps.InfoWindow({
      content: name
    });

    // hmmmm, I wonder what this is about...
    google.maps.event.addListener(marker, 'click', function() {
      // your code goes here!
    });

    // this is where the pin actually gets added to the map.
    // bounds.extend() takes in a map location object
    bounds.extend(new google.maps.LatLng(lat, lon));
    // fit the map to the new marker
    map.fitBounds(bounds);
    // center the map
    map.setCenter(bounds.getCenter());
  }

  /*
  callback(results, status) makes sure the search returned results for a location.
  If so, it creates a new map marker for that location.
  */
  function callback(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
      createMapMarker(results[0]);
    }
  }

  /*
  pinPoster(locations) takes in the array of locations created by locationFinder()
  and fires off Google place searches for each location
  */
  function pinPoster(locations) {

    // creates a Google place search service object. PlacesService does the work of
    // actually searching for location data.
    var service = new google.maps.places.PlacesService(map);

    // Iterates through the array of locations, creates a search object for each location
    for (var place in locations) {

      // the search request object
      var request = {
        query: locations[place]
      };

      // Actually searches the Google Maps API for location data and runs the callback
      // function with the search results after each search.
      service.textSearch(request, callback);
    }
  }

  // Sets the boundaries of the map based on pin locations
  window.mapBounds = new google.maps.LatLngBounds();

  // locations is an array of location strings returned from locationFinder()
  locations = locationFinder();

  // pinPoster(locations) creates pins on the map for each location in
  // the locations array
  pinPoster(locations);

}

/*
Uncomment the code below when you're ready to implement a Google Map!
*/

// Calls the initializeMap() function when the page loads
//window.addEventListener('load', initializeMap);

// Vanilla JS way to listen for resizing of the window
// and adjust map bounds
//window.addEventListener('resize', function(e) {
  //Make sure the map bounds get updated on page resize
//  map.fitBounds(mapBounds);
//});
<commit_msg>Update helper.js<commit_after>/*

This file contains all of the code running in the background that makes resumeBuilder.js possible. We call these helper functions because they support your code in this course.

Don't worry, you'll learn what's going on in this file throughout the course. You won't need to make any changes to it until you start experimenting with inserting a Google Map in Problem Set 3.

Cameron Pittman
*/

/*
These are HTML strings. As part of the course, you'll be using JavaScript functions
replace the %data% placeholder text you see in them.
*/
var HTMLheaderName = '
%data%
';
var HTMLheaderRole = '%data%
';

var HTMLcontactGeneric = '
%contact%%data%
';
var HTMLmobile = '
mobile%data%
';
var HTMLemail = '
email%data%
';
var HTMLtwitter = '
twitter%data%
';
var HTMLgithub = '
github%data%
';
var HTMLblog = '
blog%data%
';
var HTMLlocation = '
location%data%
';

var HTMLbioPic = '';
var HTMLwelcomeMsg = '%data%';

var HTMLskillsStart = '
Skills at a Glance:

';
var HTMLskills = '
%data%
';

var HTMLworkStart = '

';
var HTMLworkEmployer = '%data%';
var HTMLworkTitle = ' - %data%';
var HTMLworkDates = '
%data%
';
var HTMLworkLocation = '
%data%
';
var HTMLworkDescription = '

%data%
';

var HTMLprojectStart = '

';
var HTMLprojectTitle = '%data%';
var HTMLprojectDates = '
%data%
';
var HTMLprojectDescription = '

%data%
';
var HTMLprojectImage = '';

var HTMLschoolStart = '

';
var HTMLschoolName = '%data%';
var HTMLschoolDegree = ' -- %data%';
var HTMLschoolDates = '
%data%
';
var HTMLschoolLocation = '
%data%
';
var HTMLschoolMajor = '
Major: %data%';

var HTMLonlineClasses = '
Online Classes
';
var HTMLonlineTitle = '%data%';
var HTMLonlineSchool = ' - %data%';
var HTMLonlineDates = '
%data%
';
var HTMLonlineURL = '
%data%';

var internationalizeButton = '<button>Internationalize</button>';
var googleMap = '

';

/*
The International Name challenge in Lesson 2 where you'll create a function that will need this helper code to run. Don't delete! It hooks up your code to the button you'll be appending.
*/
$(document).ready(function() {
  $('button').click(function() {
    var iName = inName() || function(){};
    $('#name').html(iName);
  });
});

/*
The next few lines about clicks are for the Collecting Click Locations quiz in Lesson 2.
*/
clickLocations = [];

function logClicks(x,y) {
  clickLocations.push(
    {
      x: x,
      y: y
    }
  );
  console.log('x location: ' + x + '; y location: ' + y);
}

$(document).click(function(loc) {
  // your code goes here!
});

/*
This is the fun part. Here's where we generate the custom Google Map for the website.
See the documentation below for more details.
https://developers.google.com/maps/documentation/javascript/reference
*/
var map;    // declares a global map variable

/*
Start here! initializeMap() is called when page is loaded.
*/
function initializeMap() {

  var locations;

  var mapOptions = {
    disableDefaultUI: true
  };

  /*
  For the map to be displayed, the googleMap var must be
  appended to #mapDiv in resumeBuilder.js.
  */
  map = new google.maps.Map(document.querySelector('#map'), mapOptions);

  /*
  locationFinder() returns an array of every location string from the JSONs
  written for bio, education, and work.
  */
  function locationFinder() {

    // initializes an empty array
    var locations = [];

    // adds the single location property from bio to the locations array
    locations.push(bio.contacts.location);

    // iterates through school locations and appends each location to
    // the locations array. Note that forEach is used for array iteration
    // as described in the Udacity FEND Style Guide:
    // https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
    education.schools.forEach(function(school){
      locations.push(school.location);
    });

    // iterates through work locations and appends each location to
    // the locations array. Note that forEach is used for array iteration
    // as described in the Udacity FEND Style Guide:
    // https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
    work.jobs.forEach(function(job){
      locations.push(job.location);
    });

    return locations;
  }

  /*
  createMapMarker(placeData) reads Google Places search results to create map pins.
  placeData is the object returned from search results containing information
  about a single location.
  */
  function createMapMarker(placeData) {

    // The next lines save location data from the search result object to local variables
    var lat = placeData.geometry.location.lat();  // latitude from the place service
    var lon = placeData.geometry.location.lng();  // longitude from the place service
    var name = placeData.formatted_address;   // name of the place from the place service
    var bounds = window.mapBounds;            // current boundaries of the map window

    // marker is an object with additional data about the pin for a single location
    var marker = new google.maps.Marker({
      map: map,
      position: placeData.geometry.location,
      title: name
    });

    // infoWindows are the little helper windows that open when you click
    // or hover over a pin on a map. They usually contain more information
    // about a location.
    var infoWindow = new google.maps.InfoWindow({
      content: name
    });

    // hmmmm, I wonder what this is about...
    google.maps.event.addListener(marker, 'click', function() {
      // your code goes here!
    });

    // this is where the pin actually gets added to the map.
    // bounds.extend() takes in a map location object
    bounds.extend(new google.maps.LatLng(lat, lon));
    // fit the map to the new marker
    map.fitBounds(bounds);
    // center the map
    map.setCenter(bounds.getCenter());
  }

  /*
  callback(results, status) makes sure the search returned results for a location.
  If so, it creates a new map marker for that location.
  */
  function callback(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
      createMapMarker(results[0]);
    }
  }

  /*
  pinPoster(locations) takes in the array of locations created by locationFinder()
  and fires off Google place searches for each location
  */
  function pinPoster(locations) {

    // creates a Google place search service object. PlacesService does the work of
    // actually searching for location data.
    var service = new google.maps.places.PlacesService(map);

    // Iterates through the array of locations, creates a search object for each location
      locations.forEach(function(place){
      // the search request object
      var request = {
        query: place
      };

      // Actually searches the Google Maps API for location data and runs the callback
      // function with the search results after each search.
      service.textSearch(request, callback);
    });
  }

  // Sets the boundaries of the map based on pin locations
  window.mapBounds = new google.maps.LatLngBounds();

  // locations is an array of location strings returned from locationFinder()
  locations = locationFinder();

  // pinPoster(locations) creates pins on the map for each location in
  // the locations array
  pinPoster(locations);

}

/*
Uncomment the code below when you're ready to implement a Google Map!
*/

// Calls the initializeMap() function when the page loads
//window.addEventListener('load', initializeMap);

// Vanilla JS way to listen for resizing of the window
// and adjust map bounds
//window.addEventListener('resize', function(e) {
  //Make sure the map bounds get updated on page resize
//  map.fitBounds(mapBounds);
//});
<|endoftext|>


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

    $("#multiptleBufferItem").on('mouseover', 'tr', function (e) {
        tempGraphicLayer.clear();
        //Changed the fill
        var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0, 0.7]));
        var row = $(this).parent().children().index($(this));
        var zoomGraphic = selectedFeatures.features[row];
        zoomGraphic.setSymbol(sfs);
        tempGraphicLayer.add(zoomGraphic);
    });

    $("#multiptleBufferItem,#multipleItem").on('mouseout', 'tr', function (e) {
        tempGraphicLayer.clear();
    });

    $("#multiptleItem").on('click', 'tr', function (e) {
        tempGraphicLayer.clear();
        //Changed the fill
        var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0]));
        var row = $(this).parent().children().index($(this));
        var zoomGraphic = selectedFeatures.features[row];
        var extent = esri.graphicsExtent([zoomGraphic]);
        var extentParcel = extent.expand(2);
        map.setExtent(extentParcel, true);
        zoomGraphic.setSymbol(sfs);
        tempGraphicLayer.add(zoomGraphic);
        doneIdentifyParcel(zoomGraphic);
    });

	$("#multiptleItem").on('mouseover', 'tr', function (e) {
        tempGraphicLayer.clear();
        //Changed the fill
        var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0, 0.7]));
        var row = $(this).parent().children().index($(this));
		console.log(row);
        var zoomGraphic = selectedFeatures.features[row];
        zoomGraphic.setSymbol(sfs);
        tempGraphicLayer.add(zoomGraphic);
    });

    $('#map-tools .middle').click(function () {
        navEvent("resetMap");
    });

    $('#map-tools .first').click(function () {
        navEvent("gps");
    });

    $('#dPoint').click(function () {
        $('#draw-tab .size-row th').html('Size');
    });

    $('#dFreePoly').click(function () {
        $('#draw-tab .size-row th').html('Opacity');
    });

    $('#dFreeLine').click(function () {
        $('#draw-tab .size-row th').html('Width');
    });

    $('#dText').click(function () {
        $('#draw-tab .size-row th').html('Size');
    });

});
<commit_msg>depreciated helper.js<commit_after>$(document).ready(function () {

    // $("#multiptleBufferItem").on('mouseover', 'tr', function (e) {
        // tempGraphicLayer.clear();
        // //Changed the fill
        // var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												// new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0, 0.7]));
        // var row = $(this).parent().children().index($(this));
        // var zoomGraphic = selectedFeatures.features[row];
        // zoomGraphic.setSymbol(sfs);
        // tempGraphicLayer.add(zoomGraphic);
    // });

    // $("#multiptleBufferItem,#multipleItem").on('mouseout', 'tr', function (e) {
        // tempGraphicLayer.clear();
    // });

    // $("#multiptleItem").on('click', 'tr', function (e) {
        // tempGraphicLayer.clear();
        // //Changed the fill
        // var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												// new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0]));
        // var row = $(this).parent().children().index($(this));
        // var zoomGraphic = selectedFeatures.features[row];
        // var extent = esri.graphicsExtent([zoomGraphic]);
        // var extentParcel = extent.expand(2);
        // map.setExtent(extentParcel, true);
        // zoomGraphic.setSymbol(sfs);
        // tempGraphicLayer.add(zoomGraphic);
        // doneIdentifyParcel(zoomGraphic);
    // });

	// $("#multiptleItem").on('mouseover', 'tr', function (e) {
        // tempGraphicLayer.clear();
        // //Changed the fill
        // var sfs = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
												// new dojo.Color([0, 0, 0]), 2), new dojo.Color([255, 0, 0, 0.7]));
        // var row = $(this).parent().children().index($(this));
		// console.log(row);
        // var zoomGraphic = selectedFeatures.features[row];
        // zoomGraphic.setSymbol(sfs);
        // tempGraphicLayer.add(zoomGraphic);
    // });

    // $('#map-tools .middle').click(function () {
        // navEvent("resetMap");
    // });

    // $('#map-tools .first').click(function () {
        // navEvent("gps");
    // });

    // $('#dPoint').click(function () {
        // $('#draw-tab .size-row th').html('Size');
    // });

    // $('#dFreePoly').click(function () {
        // $('#draw-tab .size-row th').html('Opacity');
    // });

    // $('#dFreeLine').click(function () {
        // $('#draw-tab .size-row th').html('Width');
    // });

    // $('#dText').click(function () {
        // $('#draw-tab .size-row th').html('Size');
    // });

});
<|endoftext|>


<commit_before>/**
 * Created by seunggabi on 2017. 2. 26..
 */

EMT.TOOL = {
	write_mode: null,
	ignore_length: null,
	field_range: null,
	isFirst: true,

	init: function(data) {
		data = data || {};
		this.write_mode = data.write_mode || EMT.CONFIG.DEFAULT.WRITE_MODE;
		this.ignore_length = data.ignore_length || EMT.CONFIG.DEFAULT.IGNORE_LENGTH;
		this.field_range = data.field_range || EMT.CONFIG.DEFAULT.FIELD_RANGE;
		EMT.LOG.status = data.log_mode || EMT.CONFIG.DEFAULT.LOG_MODE;

		let isDuplication = data.isDuplication || EMT.CONFIG.DEFAULT.isDuplication;
		EMT.DATA.setDataConfig(isDuplication, this.field_range);

		EMT.STATISTICS.times = this.write_mode === EMT.CONFIG.WRITE_MODE.ALL ? 2 : 1;
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT Start");
	},

	binaryFile: function(fileName, binary) {
		this.fileName = fileName;
		this.binary = binary;
	},

	readBinaryFiles: function(binaryFiles) {
		let wbList = [];
		binaryFiles.forEach(function(binaryFile) {
			let wb = XLSX.read(binaryFile.binary, {type:"binary", cellStyles: true});
			wb.fileName = binaryFile.fileName;
			wbList.push(wb);

			EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Load File: "+binaryFile.fileName);
			EMT.STATISTICS.analyze(wb);
		}.bind(this));

		return wbList;
	},

	selectXLSX: function(fileNames) {
		let filesXLSX = [];

		fileNames.forEach(function(fileName) {
			if(fileName.lastIndexOf(EMT.CONFIG.EXTENSION) >= 0
				&& fileName.lastIndexOf(EMT.CONFIG.USING_CHECK) < 0) {
				filesXLSX.push(fileName);
			}
		}.bind(this));
		return filesXLSX;
	},

	_mergeSheets: function(wbList) {
		for(let s in wbList[0].Sheets) {
			this._setDefaultStyle(wbList[0].Sheets[s]);
		}
		return wbList.reduce(this._mergeSheet.bind(this));
	},

	_mergeSheet: function(wb1, wb2) {
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.MERGE, "TO "+wb1.fileName+", FROM "+wb2.fileName);

		for(let s in wb2.Sheets) {
			if(wb1.Sheets.hasOwnProperty(s)) {
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.CONFLICT, s+" Sheet ==> Conflict");
				wb1.Sheets[s].fileName = wb1.fileName;
				wb2.Sheets[s].fileName = wb2.fileName;
				wb1.Sheets[s] = this._mergeCells(wb1.Sheets[s], wb2.Sheets[s]);
			} else {
				EMT.LOG.addItem(EMT.LOG_TYPE.NEW, s+" Sheet ==> New");
				wb1.Sheets[s] = wb2.Sheets[s];
				wb1.SheetNames.push(s);
			}
			wb1.Sheets[s].isMerge = true;
		}
		return wb1;
	},

	_mergeCells: function(s1, s2) {
		this._setCellFomula(s1);
		this._setCellFomula(s2);
		this._setDefaultStyle(s2);

		for(let c in s2) {
			let v2 = String(s2[c].v);
			v2 = EMT.UTIL.enterOnce(v2);

			if(s1.hasOwnProperty(c)) {
				let v1 = EMT.UTIL.enterOnce(String(s1[c].v));

				if(c === EMT.CONFIG.KEY.RANGE) {
					this._extendsRange(s1[c], s2[c]);
				}
				else if(v1.length < this.ignore_length && v2.length < this.ignore_length) {
					v1 = v1.toUpperCase();
					v2 = v2.toUpperCase();

					if(v1 === v2) {
						s1[c].t = "s";
						s1[c].v = v1;
					} else {
						s1[c].v = EMT.UTIL.trim(v1 + String.fromCharCode(13) + v2);
					}
				}
				else if(!EMT.UTIL.isInclude(v1, v2)) {
					s1[c].t = "s";
					if(this.write_mode === EMT.CONFIG.WRITE_MODE.CONFLICT && s1[c].v !== "") {
						s1[c].s = EMT.CONFIG.CONFLICT_STYLE;
					}

					if(!s1.isMerge) {
						s1[c].v = this._concatFileName(s1.fileName, v1)
							+ String.fromCharCode(13)
							+ this._concatFileName(s2.fileName, v2);
					} else {
						s1[c].v += String.fromCharCode(13)
							+ this._concatFileName(s2.fileName, v2);
					}

					s1[c].v = EMT.UTIL.trim(s1[c].v);
					if(s1[c].v) {
						EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.CONFLICT, c + " Cell ==> Conflict (" + s1[c].v + ")");
					}
				}
			} else {
				if(v2.length < this.ignore_length) {
					s2[c].v = v2;
				} else {
					s2[c].v =  this._concatFileName(s2.fileName, v2);
				}
				s1[c] = s2[c];
			}
		}
		return s1;
	},

	_setDefaultStyle: function(s) {
		for(let c in s) {
			if(c.match(EMT.CONFIG.REG.CELL)) {
				s[c].s = s[c].s || {};
				s[c].s = EMT.UTIL.mix(EMT.UTIL.clone(s[c].s), EMT.CONFIG.DEFAULT_STYLE);
			}
		}
	},

	_setCellFomula: function(s) {
		for(let c in s) {
			if(s[c].hasOwnProperty && s[c].hasOwnProperty(EMT.CONFIG.KEY.FORMULA)) {
				s[c].t = "s";
				s[c].v = "="+s[c].f;
			}
		}
	},

	_extendsRange: function(r1, r2) {
		let r;
		let r1Col = r1.match(EMT.CONFIG.REG.COL);
		let r1Row = r1.match(EMT.CONFIG.REG.ROW);

		let r2Col = r2.match(EMT.CONFIG.REG.COL);
		let r2Row = r2.match(EMT.CONFIG.REG.ROW);

		r = EMT.UTIL.min(r1Col[0], r2Col[0])
			+ EMT.UTIL.min(r1Row[0], r2Row[0])
			+ ":"
			+ EMT.UTIL.max(r1Col[1], r2Col[1])
			+ EMT.UTIL.max(r1Row[1], r2Row[1]);

		return r;
	},

	_concatFileName: function(fileName, text) {
		if(text === "") {
			return text;
		}

		let fileNameLabel = "["+fileName+"]";
		if(text.indexOf(fileNameLabel) >= 0) {
			fileNameLabel = "";
		}

		let concatText = text;
		if(this.write_mode === EMT.CONFIG.WRITE_MODE.CONFLICT) {
			concatText = fileNameLabel + String.fromCharCode(13) + text;
		}

		return concatText;
	},

	writeFile: function(wbList) {
		switch(this.write_mode) {
			case EMT.CONFIG.WRITE_MODE.LIST:
			case EMT.CONFIG.WRITE_MODE.NONE:
			case EMT.CONFIG.WRITE_MODE.CONFLICT:
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				EMT.LOG.writeFile();
				break;
			case EMT.CONFIG.WRITE_MODE.ALL:
				this.write_mode = EMT.CONFIG.WRITE_MODE.NONE;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				this.write_mode = EMT.CONFIG.WRITE_MODE.CONFLICT;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				this.write_mode = EMT.CONFIG.WRITE_MODE.ALL;
				EMT.LOG.writeFile();
				break;
			default:
				console.log(EMT.CONFIG.MSG.UNDEFINED);
		}
	},

	writeBinaryFile: function(wbList) {
		let binaryFiles = [];
		switch(this.write_mode) {
			case EMT.CONFIG.WRITE_MODE.LIST:
			case EMT.CONFIG.WRITE_MODE.NONE:
			case EMT.CONFIG.WRITE_MODE.CONFLICT:
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT END");
				binaryFiles.push(new this.binaryFile(EMT.CONFIG.WRITE_NAME.LOG, EMT.LOG.getBinaryFile()));
				break;
			case EMT.CONFIG.WRITE_MODE.ALL:
				this.write_mode = EMT.CONFIG.WRITE_MODE.NONE;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				this.write_mode = EMT.CONFIG.WRITE_MODE.CONFLICT;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				this.write_mode = EMT.CONFIG.WRITE_MODE.ALL;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT END");
				binaryFiles.push(new this.binaryFile(EMT.CONFIG.WRITE_NAME.LOG, EMT.LOG.getBinaryFile()));
				break;
			default:
				console.log(EMT.CONFIG.MSG.UNDEFINED);
		}
		return binaryFiles;
	},

	_writeBinaryFile: function(wbList) {
		let wb;

		if(this.write_mode === EMT.CONFIG.WRITE_MODE.LIST) {
			wb = this._addSheets(wbList);
		} else {
			wb = this._mergeSheets(wbList);
		}

		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Write File: "+EMT.CONFIG.WRITE_NAME[this.write_mode]);
		return new this.binaryFile(EMT.CONFIG.WRITE_NAME[this.write_mode], XLSX.write(wb, {type: "binary"}));
	},

	_readSheets: function(wb) {
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Read File: "+wb.fileName);
		for(let s in wb.Sheets) {
			EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Read Sheet: "+s);
			let items = this._readCells(s, wb.Sheets[s]);
			items.forEach(function(item, index) {
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.NEW, "New Item("+Number(1+index)+"): "+item);
			}.bind(this));
		}
	},

	_readCells: function(sheetName, sheet) {
		return EMT.DATA.readCells(sheetName, sheet);
	},

	_addSheets: function(wbList) {
		EMT.DATA.init();

		for (let wb in wbList) {
			this._readSheets(wbList[wb]);
		}

		if (wbList[0].hasOwnProperty("Sheets")) {
			for (let s in wbList[0].Sheets) {
				EMT.DATA.addSheet(s, wbList[0].Sheets[s]);
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.NEW, s + " New Data Count: " + EMT.DATA.sizes[s]);
			}
			return wbList[0];
		}
	}
};<commit_msg>foreach bind(this) 제거<commit_after>/**
 * Created by seunggabi on 2017. 2. 26..
 */

EMT.TOOL = {
	write_mode: null,
	ignore_length: null,
	field_range: null,
	isFirst: true,

	init: function(data) {
		data = data || {};
		this.write_mode = data.write_mode || EMT.CONFIG.DEFAULT.WRITE_MODE;
		this.ignore_length = data.ignore_length || EMT.CONFIG.DEFAULT.IGNORE_LENGTH;
		this.field_range = data.field_range || EMT.CONFIG.DEFAULT.FIELD_RANGE;
		EMT.LOG.status = data.log_mode || EMT.CONFIG.DEFAULT.LOG_MODE;

		let isDuplication = data.isDuplication || EMT.CONFIG.DEFAULT.isDuplication;
		EMT.DATA.setDataConfig(isDuplication, this.field_range);

		EMT.STATISTICS.times = this.write_mode === EMT.CONFIG.WRITE_MODE.ALL ? 2 : 1;
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT Start");
	},

	binaryFile: function(fileName, binary) {
		this.fileName = fileName;
		this.binary = binary;
	},

	readBinaryFiles: function(binaryFiles) {
		let wbList = [];
		binaryFiles.forEach((binaryFile) => {
			let wb = XLSX.read(binaryFile.binary, {type:"binary", cellStyles: true});
			wb.fileName = binaryFile.fileName;
			wbList.push(wb);

			EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Load File: "+binaryFile.fileName);
			EMT.STATISTICS.analyze(wb);
		});

		return wbList;
	},

	selectXLSX: function(fileNames) {
		let filesXLSX = [];

		fileNames.forEach((fileName) => {
			if(fileName.lastIndexOf(EMT.CONFIG.EXTENSION) >= 0
				&& fileName.lastIndexOf(EMT.CONFIG.USING_CHECK) < 0) {
				filesXLSX.push(fileName);
			}
		});
		return filesXLSX;
	},

	_mergeSheets: function(wbList) {
		for(let s in wbList[0].Sheets) {
			this._setDefaultStyle(wbList[0].Sheets[s]);
		}
		return wbList.reduce(this._mergeSheet.bind(this));
	},

	_mergeSheet: function(wb1, wb2) {
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.MERGE, "TO "+wb1.fileName+", FROM "+wb2.fileName);

		for(let s in wb2.Sheets) {
			if(wb1.Sheets.hasOwnProperty(s)) {
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.CONFLICT, s+" Sheet ==> Conflict");
				wb1.Sheets[s].fileName = wb1.fileName;
				wb2.Sheets[s].fileName = wb2.fileName;
				wb1.Sheets[s] = this._mergeCells(wb1.Sheets[s], wb2.Sheets[s]);
			} else {
				EMT.LOG.addItem(EMT.LOG_TYPE.NEW, s+" Sheet ==> New");
				wb1.Sheets[s] = wb2.Sheets[s];
				wb1.SheetNames.push(s);
			}
			wb1.Sheets[s].isMerge = true;
		}
		return wb1;
	},

	_mergeCells: function(s1, s2) {
		this._setCellFomula(s1);
		this._setCellFomula(s2);
		this._setDefaultStyle(s2);

		for(let c in s2) {
			let v2 = String(s2[c].v);
			v2 = EMT.UTIL.enterOnce(v2);

			if(s1.hasOwnProperty(c)) {
				let v1 = EMT.UTIL.enterOnce(String(s1[c].v));

				if(c === EMT.CONFIG.KEY.RANGE) {
					this._extendsRange(s1[c], s2[c]);
				}
				else if(v1.length < this.ignore_length && v2.length < this.ignore_length) {
					v1 = v1.toUpperCase();
					v2 = v2.toUpperCase();

					if(v1 === v2) {
						s1[c].t = "s";
						s1[c].v = v1;
					} else {
						s1[c].v = EMT.UTIL.trim(v1 + String.fromCharCode(13) + v2);
					}
				}
				else if(!EMT.UTIL.isInclude(v1, v2)) {
					s1[c].t = "s";
					if(this.write_mode === EMT.CONFIG.WRITE_MODE.CONFLICT && s1[c].v !== "") {
						s1[c].s = EMT.CONFIG.CONFLICT_STYLE;
					}

					if(!s1.isMerge) {
						s1[c].v = this._concatFileName(s1.fileName, v1)
							+ String.fromCharCode(13)
							+ this._concatFileName(s2.fileName, v2);
					} else {
						s1[c].v += String.fromCharCode(13)
							+ this._concatFileName(s2.fileName, v2);
					}

					s1[c].v = EMT.UTIL.trim(s1[c].v);
					if(s1[c].v) {
						EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.CONFLICT, c + " Cell ==> Conflict (" + s1[c].v + ")");
					}
				}
			} else {
				if(v2.length < this.ignore_length) {
					s2[c].v = v2;
				} else {
					s2[c].v =  this._concatFileName(s2.fileName, v2);
				}
				s1[c] = s2[c];
			}
		}
		return s1;
	},

	_setDefaultStyle: function(s) {
		for(let c in s) {
			if(c.match(EMT.CONFIG.REG.CELL)) {
				s[c].s = s[c].s || {};
				s[c].s = EMT.UTIL.mix(EMT.UTIL.clone(s[c].s), EMT.CONFIG.DEFAULT_STYLE);
			}
		}
	},

	_setCellFomula: function(s) {
		for(let c in s) {
			if(s[c].hasOwnProperty && s[c].hasOwnProperty(EMT.CONFIG.KEY.FORMULA)) {
				s[c].t = "s";
				s[c].v = "="+s[c].f;
			}
		}
	},

	_extendsRange: function(r1, r2) {
		let r;
		let r1Col = r1.match(EMT.CONFIG.REG.COL);
		let r1Row = r1.match(EMT.CONFIG.REG.ROW);

		let r2Col = r2.match(EMT.CONFIG.REG.COL);
		let r2Row = r2.match(EMT.CONFIG.REG.ROW);

		r = EMT.UTIL.min(r1Col[0], r2Col[0])
			+ EMT.UTIL.min(r1Row[0], r2Row[0])
			+ ":"
			+ EMT.UTIL.max(r1Col[1], r2Col[1])
			+ EMT.UTIL.max(r1Row[1], r2Row[1]);

		return r;
	},

	_concatFileName: function(fileName, text) {
		if(text === "") {
			return text;
		}

		let fileNameLabel = "["+fileName+"]";
		if(text.indexOf(fileNameLabel) >= 0) {
			fileNameLabel = "";
		}

		let concatText = text;
		if(this.write_mode === EMT.CONFIG.WRITE_MODE.CONFLICT) {
			concatText = fileNameLabel + String.fromCharCode(13) + text;
		}

		return concatText;
	},

	writeFile: function(wbList) {
		switch(this.write_mode) {
			case EMT.CONFIG.WRITE_MODE.LIST:
			case EMT.CONFIG.WRITE_MODE.NONE:
			case EMT.CONFIG.WRITE_MODE.CONFLICT:
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				EMT.LOG.writeFile();
				break;
			case EMT.CONFIG.WRITE_MODE.ALL:
				this.write_mode = EMT.CONFIG.WRITE_MODE.NONE;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				this.write_mode = EMT.CONFIG.WRITE_MODE.CONFLICT;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				this._writeFile(EMT.UTIL.clone(wbList));
				this.write_mode = EMT.CONFIG.WRITE_MODE.ALL;
				EMT.LOG.writeFile();
				break;
			default:
				console.log(EMT.CONFIG.MSG.UNDEFINED);
		}
	},

	writeBinaryFile: function(wbList) {
		let binaryFiles = [];
		switch(this.write_mode) {
			case EMT.CONFIG.WRITE_MODE.LIST:
			case EMT.CONFIG.WRITE_MODE.NONE:
			case EMT.CONFIG.WRITE_MODE.CONFLICT:
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT END");
				binaryFiles.push(new this.binaryFile(EMT.CONFIG.WRITE_NAME.LOG, EMT.LOG.getBinaryFile()));
				break;
			case EMT.CONFIG.WRITE_MODE.ALL:
				this.write_mode = EMT.CONFIG.WRITE_MODE.NONE;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				this.write_mode = EMT.CONFIG.WRITE_MODE.CONFLICT;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Mode is "+this.write_mode);
				binaryFiles.push(this._writeBinaryFile(EMT.UTIL.clone(wbList)));
				this.write_mode = EMT.CONFIG.WRITE_MODE.ALL;
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "EMT END");
				binaryFiles.push(new this.binaryFile(EMT.CONFIG.WRITE_NAME.LOG, EMT.LOG.getBinaryFile()));
				break;
			default:
				console.log(EMT.CONFIG.MSG.UNDEFINED);
		}
		return binaryFiles;
	},

	_writeBinaryFile: function(wbList) {
		let wb;

		if(this.write_mode === EMT.CONFIG.WRITE_MODE.LIST) {
			wb = this._addSheets(wbList);
		} else {
			wb = this._mergeSheets(wbList);
		}

		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Write File: "+EMT.CONFIG.WRITE_NAME[this.write_mode]);
		return new this.binaryFile(EMT.CONFIG.WRITE_NAME[this.write_mode], XLSX.write(wb, {type: "binary"}));
	},

	_readSheets: function(wb) {
		EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Read File: "+wb.fileName);
		for(let s in wb.Sheets) {
			EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.SYSTEM, "Read Sheet: "+s);
			let items = this._readCells(s, wb.Sheets[s]);
			items.forEach((item, index) => {
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.NEW, "New Item("+Number(1+index)+"): "+item);
			});
		}
	},

	_readCells: function(sheetName, sheet) {
		return EMT.DATA.readCells(sheetName, sheet);
	},

	_addSheets: function(wbList) {
		EMT.DATA.init();

		for (let wb in wbList) {
			this._readSheets(wbList[wb]);
		}

		if (wbList[0].hasOwnProperty("Sheets")) {
			for (let s in wbList[0].Sheets) {
				EMT.DATA.addSheet(s, wbList[0].Sheets[s]);
				EMT.LOG.addItem(EMT.CONFIG.LOG_TYPE.NEW, s + " New Data Count: " + EMT.DATA.sizes[s]);
			}
			return wbList[0];
		}
	}
};<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @emails oncall+javascript_foundation
 */

'use strict';

jest.mock('path');
jest.mock('fs');

let plistPath = null;
jest.mock('../../ios/getPlistPath', () => () => plistPath);

const {readFileSync} = require.requireActual('fs');
const fs = require('fs');

const xcode = require('xcode');
const path = require('path');
const writePlist = require('../../ios/writePlist');

const projectPath = path.join(__dirname, '../../__fixtures__/project.pbxproj');
const infoPlistPath = path.join(__dirname, '../../__fixtures__/Info.plist');

fs.readFileSync = jest.fn(() => readFileSync(projectPath).toString());

const {writeFileSync} = fs;
fs.writeFileSync = jest.fn(writeFileSync);

const project = xcode.project('/Basic/project.pbxproj');

const plist = {
  CFBundleDevelopmentRegion: 'en',
  UISupportedInterfaceOrientations: ['UIInterfaceOrientationPortrait'],
};

describe('ios::writePlist', () => {
  beforeEach(() => {
    project.parseSync();
    fs.writeFileSync.mockReset();
  });

  it('should write a `.plist` file', () => {
    plistPath = '/Basic/Info.plist';
    const result = writePlist(project, '/', plist);
    const infoPlist = readFileSync(infoPlistPath).toString();
    expect(fs.writeFileSync).toHaveBeenCalledWith(plistPath, infoPlist);
  });

  it('when plistPath is null it should return null', () => {
    plistPath = null;
    expect(writePlist(project, '/', plist)).toBeNull();
    expect(fs.writeFileSync).not.toHaveBeenCalled();
  });
});
<commit_msg>react-native: fix path module use in writePlist test<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @emails oncall+javascript_foundation
 */

'use strict';

jest.mock('path');
jest.mock('fs');

let plistPath = null;
jest.mock('../../ios/getPlistPath', () => () => plistPath);

const {readFileSync} = require.requireActual('fs');
const fs = require('fs');

const xcode = require('xcode');
const writePlist = require('../../ios/writePlist');

const realPath = require.requireActual('path');
const projectPath = realPath.join(
  __dirname,
  '../../__fixtures__/project.pbxproj',
);
const infoPlistPath = realPath.join(__dirname, '../../__fixtures__/Info.plist');

fs.readFileSync = jest.fn(() => readFileSync(projectPath).toString());

const {writeFileSync} = fs;
fs.writeFileSync = jest.fn(writeFileSync);

const project = xcode.project('/Basic/project.pbxproj');

const plist = {
  CFBundleDevelopmentRegion: 'en',
  UISupportedInterfaceOrientations: ['UIInterfaceOrientationPortrait'],
};

describe('ios::writePlist', () => {
  beforeEach(() => {
    project.parseSync();
    fs.writeFileSync.mockReset();
  });

  it('should write a `.plist` file', () => {
    plistPath = '/Basic/Info.plist';
    const result = writePlist(project, '/', plist);
    const infoPlist = readFileSync(infoPlistPath).toString();
    expect(fs.writeFileSync).toHaveBeenCalledWith(plistPath, infoPlist);
  });

  it('when plistPath is null it should return null', () => {
    plistPath = null;
    expect(writePlist(project, '/', plist)).toBeNull();
    expect(fs.writeFileSync).not.toHaveBeenCalled();
  });
});
<|endoftext|>


<commit_before>/*
Process Flow:
1. Pass the Google Search Query to Wolfram|Alpha and get the result as XML
2. Parse that XML to get a HTML-Object of the Result
3. Inject this object beautifully into the Google Site
*/

// Start when DOM is ready
$( document ).ready(function() {
    requestWolframResult(getSearchQuery());
});

/*
Get search query string (eg. sunrise+munich)
returns searcg query
*/
function getSearchQuery() {
	var searchQuery = document.getElementById('gbqfq').value.replace(/ /g, "+");
	console.log("searchQuery: "+searchQuery);
	return searchQuery;
}

/*
Get and Parse the Wolfram|Alpha result XML
*/
function requestWolframResult(searchQuery) {
	var xmlhttp = new XMLHttpRequest();

	xmlhttp.onreadystatechange = function(){
	  if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
			xmlDoc=xmlhttp.responseXML;
			/* Plaintext Result */
			var pods = xmlDoc.getElementsByTagName("pod");
			var plaintexts = xmlDoc.getElementsByTagName("plaintext");
			txt = "";
			// Skip first pod
			for (i=1; i<4; i++){
				// Get pod title
				txt = txt + pods[i].getAttribute("title") + ": ";
				console.log("pod #"+i+" title: "+pods[i].getAttribute("title"));
				// Get value of "plaintext"-node
				txt = txt + plaintexts[i].textContent + ".  ";
				console.log("plaintext #"+i+" : "+plaintexts[i].textContent);
			}

			// inject and fill result div
			displayResults(plaintexts[1].textContent, pods[i].getAttribute("title"));
		}
	  }
	// http://api.wolframalpha.com/v2/query?input="+searchQuery+"&appid=8X6XE5-Q5887TY7TE
	xmlhttp.open("GET","http://api.wolframalpha.com/v2/query?input="+searchQuery+"&appid=8X6XE5-Q5887TY7TE",true);
	xmlhttp.send();
}
function displayResults(result, description, searchQuery) {
	// Result
	var resultDiv = document.createElement("div");
	resultDiv.id = "resultDiv";
	// Description
	var descriptionDiv = document.createElement("div");
	descriptionDiv.id = "description";
	// More link
	var moreLink = document.createElement("a");
	moreLink.id = "moreLink";

	// Set content of result div and description
	resultDiv.innerHTML = result;
	descriptionDiv.innerHTML = description;
	// More link
	moreLink.appendChild(document.createTextNode("More"));
	moreLink.title = "More2";
	moreLink.href = "http://www.wolframalpha.com/input/?i="+searchQuery;
	// Insert result div into DOM

	document.getElementById("rcnt").parentNode.insertBefore(resultDiv, document.getElementById("rcnt"));
	// Add Description and more link into resultDiv
	document.getElementById("resultDiv").appendChild(descriptionDiv);
	document.getElementById("resultDiv").appendChild(moreLink);
}<commit_msg>Fixed error with more link<commit_after>/*
Process Flow:
1. Pass the Google Search Query to Wolfram|Alpha and get the result as XML
2. Parse that XML to get a HTML-Object of the Result
3. Inject this object beautifully into the Google Site
*/

// Start when DOM is ready
$( document ).ready(function() {
    requestWolframResult(getSearchQuery());
});

/*
Get search query string (eg. sunrise+munich)
returns searcg query
*/
function getSearchQuery() {
	var searchQuery = document.getElementById('gbqfq').value.replace(/ /g, "+");
	console.log("searchQuery: "+searchQuery);
	return searchQuery;
}

/*
Get and Parse the Wolfram|Alpha result XML
*/
function requestWolframResult(searchQuery) {
	var xmlhttp = new XMLHttpRequest();

	xmlhttp.onreadystatechange = function(){
	  if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
			xmlDoc=xmlhttp.responseXML;
			/* Plaintext Result */
			var pods = xmlDoc.getElementsByTagName("pod");
			var plaintexts = xmlDoc.getElementsByTagName("plaintext");
			txt = "";
			// Skip first pod
			for (i=1; i<4; i++){
				// Get pod title
				txt = txt + pods[i].getAttribute("title") + ": ";
				console.log("pod #"+i+" title: "+pods[i].getAttribute("title"));
				// Get value of "plaintext"-node
				txt = txt + plaintexts[i].textContent + ".  ";
				console.log("plaintext #"+i+" : "+plaintexts[i].textContent);
			}

			// inject and fill result div
			displayResults(plaintexts[1].textContent, pods[i].getAttribute("title"), searchQuery);
		}
	  }
	xmlhttp.open("GET","http://api.wolframalpha.com/v2/query?input="+searchQuery+"&appid=8X6XE5-Q5887TY7TE",true);
	xmlhttp.send();
}

function displayResults(result, description, searchQuery) {
	// Result
	var resultDiv = document.createElement("div");
	resultDiv.id = "resultDiv";
	// Description
	var descriptionDiv = document.createElement("div");
	descriptionDiv.id = "description";
	// More link
	var moreLink = document.createElement("a");
	moreLink.id = "moreLink";

	// Set content of result div and description
	resultDiv.innerHTML = result;
	descriptionDiv.innerHTML = description;
	// More link
	moreLink.appendChild(document.createTextNode("More"));
	moreLink.title = "More2";
	moreLink.href = "http://www.wolframalpha.com/input/?i="+searchQuery;
	moreLink.target = "_blank";

	// Insert result div into DOM
	document.getElementById("rcnt").parentNode.insertBefore(resultDiv, document.getElementById("rcnt"));
	// Add Description and more link into resultDiv
	document.getElementById("resultDiv").appendChild(descriptionDiv);
	document.getElementById("resultDiv").appendChild(moreLink);
}<|endoftext|>