<commit_before>$(document).ready(function(){ // wait for page to finish loading before executing jQuery code
    "use strict";

    noXSS();

    // trigger ajax on CR drop-down to populate revision select
    $("#id_coderesource").on('change', function() {
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(
                "/api/coderesources/" + cr_id + "/revisions/",
                {}, // specify data as an object
                function(result) {
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_driver_revisions").empty().append(options);
                }
            );
        }
        else {
            $("#id_driver_revisions").html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    /* populate CR revision dropdown on selection of CodeResource
     * By *delegating* this event to #dependencyForms rather than each select.coderesource
     * directly, new dynamically-generated selects retain this behaviour. */
    $("#dependencyForms").on('change', 'select.coderesource', function() {
        var suffix = this.id.split('_')[2];
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(// shorthand for $.ajax where datatype is JSON and request method is GET. also parses JSON automatically.
                "/api/coderesources/" + cr_id + "/revisions/", // url
                {}, // specify data as an object
                function (result) { // callback for successful request
                    /* String appends are *much* faster than array joins in JS.
                     * More info at http://jsperf.com/append-string-vs-join-array
                     */
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_revisions_" + suffix).empty().append(options);
                }
            );
        }
        else {
            $("#id_revisions_" + suffix).html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    var dep_coderesource_options = document.getElementById("id_coderesource_0").options,
        numberOfDepForms = $('#dependencyForms > tr').length;

    // modify name attributes for extra input forms received from server
    for (var i = 0; i < numberOfDepForms; i++) {
        $('#id_coderesource_'+i).attr('name', 'coderesource_'+i);
        $('#id_revisions_'+i).attr('name', 'revisions_'+i);
        $('#id_path_'+i).attr('name', 'path_'+i);
        $('#id_filename_'+i).attr('name', 'filename_'+i);
    }

    // query button by id selector
    $("#addDependencyForm").click(function() {
        numberOfDepForms += 1;
        i = numberOfDepForms - 1; // zero-based index
        var $dependencyRow = $('
'),
            $select = $('<select class="coderesource" id="id_coderesource_' + i + '" name="coderesource_' + i + '">');

        for (var j = 0; j < dep_coderesource_options.length; j++) {
            $select.append($('<option>')
                    .attr('value', dep_coderesource_options[j].value)
                    .text(dep_coderesource_options[j].text));
        }

        $dependencyRow.append($('').append($select));
        $dependencyRow.append(
                '<select class="revisions" id="id_revisions_' + i + '" ' +
                'name="revisions_' + i + '">\n' +
                '<option value="" selected="selected">--- select a ' +
                'CodeResource first ---</option></select>	\n');

        // generate char fields
        $dependencyRow.append(
                '<input id="id_path_' + i + '" maxlength="255" ' +
                'name="path_' + i + '" type="text">	\n' +
                '<input id="id_filename_' + i + '" maxlength="255" ' +
                'name="filename_' + i + '" type="text">	\n');

        $('#dependencyForms').find('tr:last').after($dependencyRow);

    });

    $("#removeDependencyForm").click(function() {
        if (numberOfDepForms > 1) {
            numberOfDepForms -= 1;
            $('#dependencyForms').find('tr:last').remove();
        }
    });

    // add or subtract input forms
    var numberOfInputForms = $('#extraInputForms > tr').length;
    var io_cdt_options = document.getElementById("id_compounddatatype_in_0").options;

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfInputForms; i++) {
        $('#id_dataset_name_in_'+i).attr('name', 'dataset_name_in_'+i);
        $('#id_compounddatatype_in_'+i).attr('name', 'compounddatatype_in_'+i);
        $('#id_min_row_in_'+i).attr('name', 'min_row_in_'+i);
        $('#id_max_row_in_'+i).attr('name', 'max_row_in_'+i);
    }

    // append row to table
    $("#addInputForm").click(
        function () {
            numberOfInputForms += 1;
            i = numberOfInputForms - 1; // 0-indexing
            var $inputRow = $('
'),
                $select;
            $inputRow.append(""+numberOfInputForms+"	");

            $inputRow.append("<input id=\"id_dataset_name_in_" + i + "\" maxlength=\"128\" name=\"dataset_name_in_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_in_" + i + "\" name=\"compounddatatype_in_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $inputRow.append($('').append($select));
            $inputRow.append("<input id=\"id_min_row_in_" + i + "\" class=\"shortIntField\" name=\"min_row_in_" + i + "\" type=\"number\" />	");
            $inputRow.append("<input id=\"id_max_row_in_" + i + "\" class=\"shortIntField\" name=\"max_row_in_" + i + "\" type=\"number\" />	");

            $('#extraInputForms').find('tr:last').after($inputRow);
        }
    );
    $("#removeInputForm").click(
        function() {
            if (numberOfInputForms > 1) {
                numberOfInputForms -= 1;
                $('#extraInputForms').find('tr:last').remove();
            }
        }
    );

    // add or subtract output forms
    var numberOfOutputForms = $('#extraOutputForms > tr').length;
    // we can reuse options

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfOutputForms; i++) {
        $('#id_dataset_name_out_'+i).attr('name', 'dataset_name_out_'+i);
        $('#id_compounddatatype_out_'+i).attr('name', 'compounddatatype_out_'+i);
        $('#id_min_row_out_'+i).attr('name', 'min_row_out_'+i);
        $('#id_max_row_out_'+i).attr('name', 'max_row_out_'+i);
    }

    // append row to table
    $("#addOutputForm").click(
        function () {
            numberOfOutputForms += 1;
            i = numberOfOutputForms - 1; // 0-indexing
            var $outputRow = $('
'),
                $select;
            $outputRow.append(""+numberOfOutputForms+"	");

            $outputRow.append("<input id=\"id_dataset_name_out_" + i + "\" maxlength=\"128\" name=\"dataset_name_out_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_out_" + i + "\" name=\"compounddatatype_out_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $outputRow.append($('').append($select));
            $outputRow.append("<input id=\"id_min_row_out_" + i + "\" class=\"shortIntField\" name=\"min_row_out_" + i + "\" type=\"number\" />	");
            $outputRow.append("<input id=\"id_max_row_out_" + i + "\" class=\"shortIntField\" name=\"max_row_out_" + i + "\" type=\"number\" />	");

            $('#extraOutputForms').find('tr:last').after($outputRow);
        }
    );
    $("#removeOutputForm").click(
        function() {
            if (numberOfOutputForms > 1) {
                numberOfOutputForms -= 1;
                $('#extraOutputForms').find('tr:last').remove();
            }
        }
    );

    // Pack help text into an unobtrusive icon
    $('.helptext', 'form').each(function() {
        var $this = $(this);
        $this.wrapInner('').prepend('?');
    });

    $('a[rel="ctrl"]').on('click', function (e) {
        $(this).siblings('.fulltext').show().css({ top: e.pageY, left: e.pageX, 'z-index': 3 });
        setTimeout(function() { $('.fulltext').fadeOut(300); }, 5000);
    });

    // hide Method Family form if a pre-existing family is selected
    $('#id_family').on('change', function() {
        this_family = $(this).val();
        if (this_family === "") {
            $('#id_name').prop('disabled', false);
            $('#id_description').prop('disabled', false);
        } else {
            // TODO: ajax query populates these fields with values from DB
            $('#id_name').prop('disabled', true);
            $('#id_description').prop('disabled', true);
        }
    }).change(); // trigger on load

    // set default MethodFamily name to name of CodeResource
    $("#id_coderesource").on("change", function () {
        $("#id_revision_name").val($(this).children("option:selected").text());
    });
});
<commit_msg>Fixes #626<commit_after>$(document).ready(function(){ // wait for page to finish loading before executing jQuery code
    "use strict";

    var cr_id;

    var $coderesource = $("#id_coderesource");
    var $dependencyForms = $("#dependencyForms");

    noXSS();

    // trigger ajax on CR drop-down to populate revision select
    $coderesource.on('change', function() {
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(
                "/api/coderesources/" + cr_id + "/revisions/",
                {}, // specify data as an object
                function(result) {
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_driver_revisions").empty().append(options);
                }
            );
        }
        else {
            $("#id_driver_revisions").html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    /* populate CR revision dropdown on selection of CodeResource
     * By *delegating* this event to #dependencyForms rather than each select.coderesource
     * directly, new dynamically-generated selects retain this behaviour. */
    $dependencyForms.on('change', 'select.coderesource', function() {
        var suffix = this.id.split('_')[2];
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(// shorthand for $.ajax where datatype is JSON and request method is GET. also parses JSON automatically.
                "/api/coderesources/" + cr_id + "/revisions/", // url
                {}, // specify data as an object
                function (result) { // callback for successful request
                    /* String appends are *much* faster than array joins in JS.
                     * More info at http://jsperf.com/append-string-vs-join-array
                     */
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_revisions_" + suffix).empty().append(options);
                }
            );
        }
        else {
            $("#id_revisions_" + suffix).html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    var dep_coderesource_options = document.getElementById("id_coderesource_0").options,
        numberOfDepForms = $dependencyForms.children('tr').length;

    // modify name attributes for extra input forms received from server
    for (var i = 0; i < numberOfDepForms; i++) {
        $('#id_coderesource_'+i).attr('name', 'coderesource_'+i);
        $('#id_revisions_'+i).attr('name', 'revisions_'+i);
        $('#id_path_'+i).attr('name', 'path_'+i);
        $('#id_filename_'+i).attr('name', 'filename_'+i);
    }

    // query button by id selector
    $("#addDependencyForm").click(function() {
        numberOfDepForms += 1;
        i = numberOfDepForms - 1; // zero-based index
        var $dependencyRow = $('
'),
            $select = $('<select class="coderesource" id="id_coderesource_' + i + '" name="coderesource_' + i + '">');

        for (var j = 0; j < dep_coderesource_options.length; j++) {
            $select.append($('<option>')
                    .attr('value', dep_coderesource_options[j].value)
                    .text(dep_coderesource_options[j].text));
        }

        $dependencyRow.append($('').append($select));
        $dependencyRow.append(
                '<select class="revisions" id="id_revisions_' + i + '" ' +
                'name="revisions_' + i + '">\n' +
                '<option value="" selected="selected">--- select a ' +
                'CodeResource first ---</option></select>	\n');

        // generate char fields
        $dependencyRow.append(
                '<input id="id_path_' + i + '" maxlength="255" ' +
                'name="path_' + i + '" type="text">	\n' +
                '<input id="id_filename_' + i + '" maxlength="255" ' +
                'name="filename_' + i + '" type="text">	\n');

        $('#dependencyForms').find('tr:last').after($dependencyRow);

    });

    $("#removeDependencyForm").click(function() {
        if (numberOfDepForms > 1) {
            numberOfDepForms -= 1;
            $('#dependencyForms').find('tr:last').remove();
        }
    });

    // add or subtract input forms
    var numberOfInputForms = $('#extraInputForms').children('tr').length;
    var io_cdt_options = document.getElementById("id_compounddatatype_in_0").options;

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfInputForms; i++) {
        $('#id_dataset_name_in_'+i).attr('name', 'dataset_name_in_'+i);
        $('#id_compounddatatype_in_'+i).attr('name', 'compounddatatype_in_'+i);
        $('#id_min_row_in_'+i).attr('name', 'min_row_in_'+i);
        $('#id_max_row_in_'+i).attr('name', 'max_row_in_'+i);
    }

    // append row to table
    $("#addInputForm").click(
        function () {
            numberOfInputForms += 1;
            i = numberOfInputForms - 1; // 0-indexing
            var $inputRow = $('
'),
                $select;
            $inputRow.append(""+numberOfInputForms+"	");

            $inputRow.append("<input id=\"id_dataset_name_in_" + i + "\" maxlength=\"128\" name=\"dataset_name_in_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_in_" + i + "\" name=\"compounddatatype_in_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $inputRow.append($('').append($select));
            $inputRow.append("<input id=\"id_min_row_in_" + i + "\" class=\"shortIntField\" name=\"min_row_in_" + i + "\" type=\"number\" />	");
            $inputRow.append("<input id=\"id_max_row_in_" + i + "\" class=\"shortIntField\" name=\"max_row_in_" + i + "\" type=\"number\" />	");

            $('#extraInputForms').find('tr:last').after($inputRow);
        }
    );
    $("#removeInputForm").click(
        function() {
            if (numberOfInputForms > 1) {
                numberOfInputForms -= 1;
                $('#extraInputForms').find('tr:last').remove();
            }
        }
    );

    // add or subtract output forms
    var numberOfOutputForms = $('#extraOutputForms').children('tr').length;
    // we can reuse options

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfOutputForms; i++) {
        $('#id_dataset_name_out_'+i).attr('name', 'dataset_name_out_'+i);
        $('#id_compounddatatype_out_'+i).attr('name', 'compounddatatype_out_'+i);
        $('#id_min_row_out_'+i).attr('name', 'min_row_out_'+i);
        $('#id_max_row_out_'+i).attr('name', 'max_row_out_'+i);
    }

    // append row to table
    $("#addOutputForm").click(
        function () {
            numberOfOutputForms += 1;
            i = numberOfOutputForms - 1; // 0-indexing
            var $outputRow = $('
'),
                $select;
            $outputRow.append(""+numberOfOutputForms+"	");

            $outputRow.append("<input id=\"id_dataset_name_out_" + i + "\" maxlength=\"128\" name=\"dataset_name_out_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_out_" + i + "\" name=\"compounddatatype_out_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $outputRow.append($('').append($select));
            $outputRow.append("<input id=\"id_min_row_out_" + i + "\" class=\"shortIntField\" name=\"min_row_out_" + i + "\" type=\"number\" />	");
            $outputRow.append("<input id=\"id_max_row_out_" + i + "\" class=\"shortIntField\" name=\"max_row_out_" + i + "\" type=\"number\" />	");

            $('#extraOutputForms').find('tr:last').after($outputRow);
        }
    );
    $("#removeOutputForm").click(
        function() {
            if (numberOfOutputForms > 1) {
                numberOfOutputForms -= 1;
                $('#extraOutputForms').find('tr:last').remove();
            }
        }
    );

    // Pack help text into an unobtrusive icon
    $('.helptext', 'form').each(function() {
        var $this = $(this);
        $this.wrapInner('').prepend('?');
    });

    $('a[rel="ctrl"]').on('click', function (e) {
        $(this).siblings('.fulltext').show().css({ top: e.pageY, left: e.pageX, 'z-index': 3 });
        setTimeout(function() { $('.fulltext').fadeOut(300); }, 5000);
    });

    // hide Method Family form if a pre-existing family is selected
    $('#id_family').on('change', function() {
        var this_family = $(this).val();
        if (this_family === "") {
            $('#id_name').prop('disabled', false);
            $('#id_description').prop('disabled', false);
        } else {
            // TODO: ajax query populates these fields with values from DB
            $('#id_name').prop('disabled', true);
            $('#id_description').prop('disabled', true);
        }
    }).change(); // trigger on load

    // set default MethodFamily name to name of CodeResource
    $coderesource.on("change", function () {
        $("#id_revision_name").val($(this).children("option:selected").text());
    });
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name        google drive video binding
// @namespace   wei
// @include     https://tw.movies.yahoo.com/movieinfo_dvd.html/id=*
// @include     http://*.atmovies.com.tw/movie/*
// @include     http://www.imdb.com/title/*
// @version     1
// @grant       none
// ==/UserScript==

var scripts = {
  'tw.movies.yahoo.com': yahoo,
  'www.atmovies.com.tw': atmovies,
  'app.atmovies.com.tw': atmovies,
  'www.imdb.com': imdb
};

var host = document.location.host;

(scripts[host] || noop)();

function googleLoginCallback(titles, _parent) {
  if(typeof titles === 'string') titles = [titles];
  return function(auth) {if(auth['access_token']) {
    var query = titles.map(function(title) {
      return 'title contains "'+title+'"';
    }).join(' or ');
    document.getElementById('signinButton').style.display = 'none';
    gapi.client.load('drive', 'v2', function() {
      gapi.client.drive.files.list({q: '('+query+') and mimeType contains "video/"'})
      .execute(addVideos(_parent));
    });
  }}

  function addVideos(_parent) {
    return function(res) {
      var height = _parent.offsetWidth * 9 / 16;
      _parent.innerHTML += res.items.map(function(video) {
        return video.title+'
'+'';
      }).join('');
    }
  }
}

function noop() {}

function yahoo() {
  var title = document
    .getElementsByClassName('bulletin')[0]
    .getElementsByTagName('h5')[0]
    .innerHTML;
}

function atmovies() {
  var title = document.querySelector('.at12b_gray').innerHTML;
  var title2 = document.querySelector('.at21b').innerHTML.replace(/<[^>]*>/g, '').replace(/[\t\r\n ]/g, '');
  unsafeWindow.loginCallback = googleLoginCallback([title, title2], document.querySelector('#movie_info01'));
  googleLogin(document.querySelector('#logo'));
}

function imdb() {
  var title = document.querySelector('#overview-top .itemprop').innerHTML;
  unsafeWindow.loginCallback = googleLoginCallback(title, document.querySelector('#title-overview-widget'));
  var _login = document.createElement('li');
  document.querySelector('#consumer_main_nav').appendChild(_login);
  googleLogin(_login);
}

function googleLogin(_parent) {
  _parent.innerHTML +=
    ''
    +'  '
    +' '
    +'';
  var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
  po.src = 'https://apis.google.com/js/client:plusone.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
}

<commit_msg>refactor<commit_after>// ==UserScript==
// @name        google drive video binding
// @namespace   wei
// @include     https://tw.movies.yahoo.com/movieinfo_dvd.html/id=*
// @include     http://*.atmovies.com.tw/movie/*
// @include     http://www.imdb.com/title/*
// @version     1
// @grant       none
// ==/UserScript==

var scripts = {
  'tw.movies.yahoo.com': yahoo,
  'www.atmovies.com.tw': atmovies,
  'app.atmovies.com.tw': atmovies,
  'www.imdb.com': imdb
};

var host = document.location.host;

(scripts[host] || noop)();

function googleLoginCallback(titles, _parent) {
  if(typeof titles === 'string') titles = [titles];
  return function(auth) {if(auth['access_token']) {
    var query = titles.map(function(title) {
      return 'title contains "'+title+'"';
    }).join(' or ');
    document.getElementById('signinButton').style.display = 'none';
    gapi.client.load('drive', 'v2', function() {
      gapi.client.drive.files.list({q: '('+query+') and mimeType contains "video/"'})
      .execute(addVideos(_parent));
    });
  }}

  function addVideos(_parent) {
    return function(res) {
      var height = _parent.offsetWidth * 9 / 16;
      _parent.innerHTML += res.items.map(function(video) {
        return [
          video.title,
          ''
        ].join('
');
      }).join('');
    }
  }
}

function noop() {}

function yahoo() {
  var title = document
    .getElementsByClassName('bulletin')[0]
    .getElementsByTagName('h5')[0]
    .innerHTML;
}

function atmovies() {
  var title = document.querySelector('.at12b_gray').innerHTML;
  var title2 = document.querySelector('.at21b').innerHTML.replace(/<[^>]*>/g, '').replace(/[\t\r\n ]/g, '');
  unsafeWindow.loginCallback = googleLoginCallback([title, title2], document.querySelector('#movie_info01'));
  googleLogin(document.querySelector('#logo'));
}

function imdb() {
  var title = document.querySelector('#overview-top .itemprop').innerHTML;
  unsafeWindow.loginCallback = googleLoginCallback(title, document.querySelector('#title-overview-widget'));
  var _login = document.createElement('li');
  document.querySelector('#consumer_main_nav').appendChild(_login);
  googleLogin(_login);
}

function googleLogin(_parent) {
  _parent.innerHTML +=
    ''
    +'  '
    +' '
    +'';
  var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
  po.src = 'https://apis.google.com/js/client:plusone.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
}

<|endoftext|>


<commit_before>/**
 * Sub-pixel optimize for canvas rendering, prevent from blur
 * when rendering a thin vertical/horizontal line.
 */

var round = Math.round;

/**
 * Sub pixel optimize line for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x1`, `x2`, `y1`, `y2` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x1]
 * @param {number} [inputShape.y1]
 * @param {number} [inputShape.x2]
 * @param {number} [inputShape.y2]
 * @param {Object} [style]
 * @param {number} [style.lineWidth]
 */
export function subPixelOptimizeLine(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }

    var x1 = inputShape.x1;
    var x2 = inputShape.x2;
    var y1 = inputShape.y1;
    var y2 = inputShape.y2;

    outputShape.x1 = x1;
    outputShape.x2 = x2;
    outputShape.y1 = y1;
    outputShape.y2 = y2;

    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return;
    }

    if (round(x1 * 2) === round(x2 * 2)) {
        outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true);
    }
    if (round(y1 * 2) === round(y2 * 2)) {
        outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true);
    }
}

/**
 * Sub pixel optimize rect for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x`, `y`, `width`, `height` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x]
 * @param {number} [inputShape.y]
 * @param {number} [inputShape.width]
 * @param {number} [inputShape.height]
 * @param {Object} [style]
 * @param {number} [style.lineWidth]
 */
export function subPixelOptimizeRect(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }

    var originX = inputShape.x;
    var originY = inputShape.y;
    var originWidth = inputShape.width;
    var originHeight = inputShape.height;

    outputShape.x = originX;
    outputShape.y = originY;
    outputShape.width = originWidth;
    outputShape.height = originHeight;

    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return;
    }

    outputShape.x = subPixelOptimize(originX, lineWidth, true);
    outputShape.y = subPixelOptimize(originY, lineWidth, true);
    outputShape.width = Math.max(
        subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x,
        originWidth === 0 ? 0 : 1
    );
    outputShape.height = Math.max(
        subPixelOptimize(originY + originHeight, lineWidth, false) - outputShape.y,
        originHeight === 0 ? 0 : 1
    );
}

/**
 * Sub pixel optimize for canvas
 *
 * @param {number} position Coordinate, such as x, y
 * @param {number} lineWidth Should be nonnegative integer.
 * @param {boolean=} positiveOrNegative Default false (negative).
 * @return {number} Optimized position.
 */
export function subPixelOptimize(position, lineWidth, positiveOrNegative) {
    // Assure that (position + lineWidth / 2) is near integer edge,
    // otherwise line will be fuzzy in canvas.
    var doubledPosition = round(position * 2);
    return (doubledPosition + round(lineWidth)) % 2 === 0
        ? doubledPosition / 2
        : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
}
<commit_msg>fix: fix the export function subPixelOptimize that access empty lineWidth.<commit_after>/**
 * Sub-pixel optimize for canvas rendering, prevent from blur
 * when rendering a thin vertical/horizontal line.
 */

var round = Math.round;

/**
 * Sub pixel optimize line for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x1`, `x2`, `y1`, `y2` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x1]
 * @param {number} [inputShape.y1]
 * @param {number} [inputShape.x2]
 * @param {number} [inputShape.y2]
 * @param {Object} [style]
 * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
 */
export function subPixelOptimizeLine(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }

    var x1 = inputShape.x1;
    var x2 = inputShape.x2;
    var y1 = inputShape.y1;
    var y2 = inputShape.y2;

    outputShape.x1 = x1;
    outputShape.x2 = x2;
    outputShape.y1 = y1;
    outputShape.y2 = y2;

    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return;
    }

    if (round(x1 * 2) === round(x2 * 2)) {
        outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true);
    }
    if (round(y1 * 2) === round(y2 * 2)) {
        outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true);
    }
}

/**
 * Sub pixel optimize rect for canvas
 *
 * @param {Object} outputShape The modification will be performed on `outputShape`.
 *                 `outputShape` and `inputShape` can be the same object.
 *                 `outputShape` object can be used repeatly, because all of
 *                 the `x`, `y`, `width`, `height` will be assigned in this method.
 * @param {Object} [inputShape]
 * @param {number} [inputShape.x]
 * @param {number} [inputShape.y]
 * @param {number} [inputShape.width]
 * @param {number} [inputShape.height]
 * @param {Object} [style]
 * @param {number} [style.lineWidth] If `null`/`undefined`/`0`, do not optimize.
 */
export function subPixelOptimizeRect(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }

    var originX = inputShape.x;
    var originY = inputShape.y;
    var originWidth = inputShape.width;
    var originHeight = inputShape.height;

    outputShape.x = originX;
    outputShape.y = originY;
    outputShape.width = originWidth;
    outputShape.height = originHeight;

    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return;
    }

    outputShape.x = subPixelOptimize(originX, lineWidth, true);
    outputShape.y = subPixelOptimize(originY, lineWidth, true);
    outputShape.width = Math.max(
        subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x,
        originWidth === 0 ? 0 : 1
    );
    outputShape.height = Math.max(
        subPixelOptimize(originY + originHeight, lineWidth, false) - outputShape.y,
        originHeight === 0 ? 0 : 1
    );
}

/**
 * Sub pixel optimize for canvas
 *
 * @param {number} position Coordinate, such as x, y
 * @param {number} lineWidth If `null`/`undefined`/`0`, do not optimize.
 * @param {boolean=} positiveOrNegative Default false (negative).
 * @return {number} Optimized position.
 */
export function subPixelOptimize(position, lineWidth, positiveOrNegative) {
    if (!lineWidth) {
        return position;
    }
    // Assure that (position + lineWidth / 2) is near integer edge,
    // otherwise line will be fuzzy in canvas.
    var doubledPosition = round(position * 2);
    return (doubledPosition + round(lineWidth)) % 2 === 0
        ? doubledPosition / 2
        : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
}
<|endoftext|>


<commit_before>"use strict";

function gsuiGridSamples() {
	var root = this._clone();

	this.rootElement = root;
	this._elPanel = root.querySelector( ".gsui-panel" );
	this._elGrid = root.querySelector( ".gsui-grid" );
	this._elPanelExt = this._elPanel.querySelector( ".gsui-extend" );
	this._elPanelCnt = this._elPanel.querySelector( ".gsui-content" );
	this._elGridCnt = this._elGrid.querySelector( ".gsui-content" );
	this._elSelection = this._elGrid.querySelector( ".gsui-select" );
	this.uiTimeLine = new gsuiTimeLine();
	this.uiBeatLines = new gsuiBeatLines();
	root.prepend( this.uiTimeLine.rootElement );
	this._elGrid.prepend( this.uiBeatLines.rootElement );

	root.oncontextmenu = function() { return false; };
	this._elPanelExt.onmousedown = this._evmdPanelEx.bind( this );
	this._elGrid.onmousedown = this._evmdGrid.bind( this );
	this._elGrid.onwheel = this._evowGrid.bind( this );
	this._elPanel.onwheel = this._evowPanel.bind( this );
	this.uiTimeLine.onchangeCurrentTime = this._evocCurrentTime.bind( this );
	this.uiTimeLine.oninputLoop = this._evoiLoop.bind( this );
	this._panelMaxWidth = Infinity;
	this._contentY =
	this._panelMinWidth =
	this._timeOffset = 0;
	this._pxPerBeat = 80;
	this.panelWidth( 100 );
}

gsuiGridSamples.prototype = {
	empty() {
		if ( this.uiTrackList ) {
			this.uiTrackList.empty();
		}
	},
	change( obj ) {
		if ( obj.tracks ) {
			this.uiTrackList.change( obj.tracks );
			this.uiTrackList.newRowElements.forEach( row => {
				row.firstChild.style.fontSize = this._pxPerBeat + "px";
				this._elGridCnt.append( row );
			} );
		}
	},
	resized() {
		var panelStyle = getComputedStyle( this._elPanel );

		this.width = this.rootElement.clientWidth;
		this._panelMinWidth = parseFloat( panelStyle.minWidth );
		this._panelMaxWidth = parseFloat( panelStyle.maxWidth ) || this.width;
		this._resizeGrid();
		this._updateGrid();
	},
	setFontSize( emPx ) {
		this._fontSize = ~~Math.min( Math.max( 16, emPx ), 256 );
		this.rootElement.style.fontSize = this._fontSize + "px";
	},
	offset( offset, beatPx ) {
		this._timeOffset = offset;
		this._pxPerBeat = beatPx || this._pxPerBeat;
		this._updateGrid( !!beatPx );
	},
	timeSignature( a, b ) {
		this.uiTimeLine.timeSignature( a, b );
		this.uiBeatLines.timeSignature( a, b );
	},
	currentTime( beat ) {
		this.uiTimeLine.currentTime( beat );
		this.uiBeatLines.currentTime( beat );
	},
	loop( a, b ) {
		this.uiTimeLine.loop( a, b );
		this.uiBeatLines.loop( a, b );
	},
	panelWidth( width ) {
		width = Math.max( this._panelMinWidth, Math.min( width, this._panelMaxWidth ) );
		if ( this._timeOffset > 0 ) {
			this._timeOffset += ( width - this._panelWidth ) / this._pxPerBeat;
		}
		this._panelWidth = width;
		this._updatePanelSize();
	},
	contentY( yEm ) {
		var h = ( this.uiTrackList || this.uiKeys ).rootElement.clientHeight;

		h = Math.max( 0, h - this._elGrid.clientHeight ) / this._fontSize;
		this._contentY = yEm = Math.min( Math.max( 0, yEm ), h );
		this._elGridCnt.style.marginTop =
		this._elPanelCnt.style.marginTop = -yEm + "em";
	},
	loadKeys( from, nbOctaves ) {
		this._loadPanelCmp( "uiKeys", "uiTrackList" );
		this.uiKeys.octaves( from, nbOctaves );
		this.uiKeys.newRowElements.forEach( ( row, i ) => {
			row.firstChild.style.fontSize = this._pxPerBeat + "px";
			row.onmousedown = this._evmdRow.bind( this, row,
				from + nbOctaves - 1 - ~~( i / 12 ) );
			this._elGridCnt.append( row );
		} );
	},
	loadTrackList() {
		this._loadPanelCmp( "uiTrackList", "uiKeys" );
		this.uiTrackList.onchange = obj => this.onchange( {
			redo: { tracks: obj.redo },
			undo: { tracks: obj.undo }
		} );
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiGridSamples.template = gsuiGridSamples.template || this._init();
		div.appendChild( document.importNode( gsuiGridSamples.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},
	_init() {
		document.body.addEventListener( "mousemove", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmmRoot( e );
		} );
		document.body.addEventListener( "mouseup", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmuRoot( e );
		} );
		return document.getElementById( "gsuiGridSamples" );
	},
	_loadPanelCmp( cmpStr, oldCmpStr ) {
		var cmp = this[ cmpStr ],
			oldCmp = this[ oldCmpStr ];

		if ( oldCmp ) {
			oldCmp.remove();
			this.setFontSize( this._fontSize * ( cmpStr === "uiKeys" ? .5 : 2 ) );
			delete this[ oldCmpStr ];
		} else {
			this.setFontSize( cmpStr === "uiKeys" ? 20 : 40 );
		}
		if ( !cmp ) {
			this[ cmpStr ] = cmp = cmpStr === "uiKeys" ? new gsuiKeys() : new gsuiTrackList();
			this._elPanelCnt.prepend( cmp.rootElement );
		}
	},
	_resizeGrid() {
		this.uiTimeLine.resized();
		this.uiBeatLines.resized();
	},
	_contentScroll( e ) {
		this.contentY( this._contentY + ( 20 * ( e.deltaY > 0 ? 1 : -1 ) ) / this._fontSize );
	},
	_getMouseBeat( e ) {
		this._elGridCntBCR = this._elGridCnt.getBoundingClientRect();
		return this.uiTimeLine._round( ( e.pageX - this._elGridCntBCR.left ) / this._pxPerBeat );
	},
	_drawSelection( e ) {
		var sty = this._elSelection.style,
			left = this._mdBeat,
			width = this._getMouseBeat( e ) - left,
			top = Math.min( this._mdTrackBCR.top, this._mmTrackBCR.top ),
			bottom = Math.max( this._mdTrackBCR.bottom, this._mmTrackBCR.bottom );

		if ( width < 0 ) {
			width = -width;
			left -= width;
		}
		sty.left = left * this._pxPerBeat + "px";
		sty.width = width * this._pxPerBeat + "px";
		sty.top = top - this._elGridCntBCR.top + "px";
		sty.height = bottom - top + "px";
	},
	_updateGrid( beatPxChanged ) {
		var beatPx = this._pxPerBeat;

		this.uiTimeLine.offset( this._timeOffset, beatPx );
		this.uiBeatLines.offset( this._timeOffset, beatPx );
		this._timeOffset = this.uiTimeLine._offset;
		this._pxPerBeat = beatPx = this.uiTimeLine._pxPerBeat;
		this._elGridCnt.style.left = -this._timeOffset * beatPx + "px";
		if ( beatPxChanged ) {
			this._elGridCnt.querySelectorAll( ".gsui-row" ).forEach( function( row ) {
				row.firstChild.style.fontSize = beatPx + "px";
			} );
		}
	},
	_updatePanelSize() {
		this._elPanel.style.width =
		this._elGrid.style.left = this._panelWidth + "px";
		this.uiTimeLine.rootElement.style.left = this._panelWidth - 1 + "px";
		this._resizeGrid();
		this._updateGrid();
	},
	_findTrack( e ) {
		return this._elGridCnt.querySelectorAll( ".gsui-row" )[
			~~( ( e.pageY - this._elGridCntBCR.top ) / this._fontSize ) ]
	},
	_createBlock( obj, elRow ) {
		var uiBlock = new gsuiAudioBlock();

		uiBlock.when( obj.when );
		uiBlock.duration( obj.duration );
		if ( obj.key ) {
			uiBlock.datatype( "key" );
			uiBlock.name( obj.key );
		}
		elRow.firstChild.append( uiBlock.rootElement );
	},

	// events:
	_evocCurrentTime( beat ) {
		this.uiBeatLines.currentTime( beat );
		this.onchangeCurrentTime && this.onchangeCurrentTime( beat );
	},
	_evoiLoop( toggle, a, b ) {
		this.uiBeatLines.loop( toggle && a, b );
		this.oninputLoop && this.oninputLoop( toggle, a, b );
	},
	_evmdGrid( e ) {
		this._mdPageX = e.pageX;
		this._mdPageY = e.pageY;
		this._mdBeat = this._getMouseBeat( e );
		gsuiGridSamples._focused = this;
		if ( e.shiftKey ) {
			this._selectionStarting = true;
		} else if ( e.altKey ) {
			this._gridDragging = true;
			this._mouseOffset = this._timeOffset;
			this._mouseContentY = this._contentY;
		}
	},
	_evmdPanelEx( e ) {
		this._rootLeft = this.rootElement.getBoundingClientRect().left;
		this._panelResizing = this._elPanelExt.clientWidth - e.layerX;
		this._elPanelExt.classList.add( "gsui-hover" );
		gsuiGridSamples._focused = this;
	},
	_evmdRow( elRow, octave, e ) {
		if ( !e.shiftKey && !e.ctrlKey && !e.altKey ) {
			if ( e.button === 0 ) {
				this._createBlock( {
					when: this._getMouseBeat( e ),
					offset: 0,
					duration: 1,
					key: elRow.dataset.key + octave
				}, elRow );
			} else if ( e.button === 2 ) {
				// ...
			}
		}
	},
	_evowGrid( e ) {
		if ( !e.shiftKey && !e.ctrlKey ) {
			this._contentScroll( e );
		} else {
			var layerX, offInc, beatPx = this._pxPerBeat;

			if ( e.ctrlKey ) {
				layerX = e.pageX - this._elGrid.getBoundingClientRect().left;
				beatPx = Math.min( Math.max( 8, beatPx * ( e.deltaY > 0 ? .9 : 1.1 ) ), 512 );
				offInc = ( layerX / this._pxPerBeat * ( beatPx - this._pxPerBeat ) ) / beatPx;
			} else {
				offInc = ( e.deltaY > 0 ? 20 : -20 ) / beatPx;
			}
			this.offset( Math.max( 0, this._timeOffset + offInc ),
				e.ctrlKey ? beatPx : undefined );
		}
		return false;
	},
	_evowPanel( e ) {
		if ( e.ctrlKey ) {
			var layerY = e.pageY - this._elPanel.getBoundingClientRect().top,
				oldFs = this._fontSize,
				fs = oldFs * ( e.deltaY > 0 ? .9 : 1.1 );

			this.setFontSize( fs );
			fs = this._fontSize;
			this.contentY( this._contentY + ( layerY / oldFs * ( fs - oldFs ) ) / fs );
		} else if ( !e.shiftKey ) {
			this._contentScroll( e );
		}
		return false;
	},
	_evmmRoot( e ) {
		var pxRel = e.pageX - this._mdPageX,
			pyRel = e.pageY - this._mdPageY;

		if ( this._gridDragging ) {
			this.offset( this._mouseOffset - pxRel / this._pxPerBeat, this._pxPerBeat );
			this.contentY( this._mouseContentY - pyRel / this._fontSize );
		} else if ( this._panelResizing != null ) {
			this.panelWidth( e.pageX - this._rootLeft + this._panelResizing );
		} else if ( this._selectionStarted ) {
			this._mmTrackBCR = this._findTrack( e ).getBoundingClientRect();
			this._drawSelection( e );
		} else if ( this._selectionStarting ) {
			if ( Math.max( Math.abs( pxRel ), Math.abs( pyRel ) ) > 6 ) {
				this._mdTrackBCR =
				this._mmTrackBCR = this._findTrack( e ).getBoundingClientRect();
				this._drawSelection( e );
				this._elSelection.classList.remove( "hidden" );
				this._selectionStarted = true;
				delete this._selectionStarting;
			}
		}
	},
	_evmuRoot( e ) {
		this._elPanelExt.classList.remove( "gsui-hover" );
		this._elSelection.classList.add( "hidden" );
		delete this._gridDragging;
		delete this._selectionStarted;
		delete this._selectionStarting;
		delete this._panelResizing;
		delete gsuiGridSamples._focused;
	}
};
<commit_msg>gsuiGridSamples: .setFontSize() -> .toggle("gs-row-tiny")<commit_after>"use strict";

function gsuiGridSamples() {
	var root = this._clone();

	this.rootElement = root;
	this._elPanel = root.querySelector( ".gsui-panel" );
	this._elGrid = root.querySelector( ".gsui-grid" );
	this._elPanelExt = this._elPanel.querySelector( ".gsui-extend" );
	this._elPanelCnt = this._elPanel.querySelector( ".gsui-content" );
	this._elGridCnt = this._elGrid.querySelector( ".gsui-content" );
	this._elSelection = this._elGrid.querySelector( ".gsui-select" );
	this.uiTimeLine = new gsuiTimeLine();
	this.uiBeatLines = new gsuiBeatLines();
	root.prepend( this.uiTimeLine.rootElement );
	this._elGrid.prepend( this.uiBeatLines.rootElement );

	root.oncontextmenu = function() { return false; };
	this._elPanelExt.onmousedown = this._evmdPanelEx.bind( this );
	this._elGrid.onmousedown = this._evmdGrid.bind( this );
	this._elGrid.onwheel = this._evowGrid.bind( this );
	this._elPanel.onwheel = this._evowPanel.bind( this );
	this.uiTimeLine.onchangeCurrentTime = this._evocCurrentTime.bind( this );
	this.uiTimeLine.oninputLoop = this._evoiLoop.bind( this );
	this._panelMaxWidth = Infinity;
	this._contentY =
	this._panelMinWidth =
	this._timeOffset = 0;
	this._pxPerBeat = 80;
	this.panelWidth( 100 );
}

gsuiGridSamples.prototype = {
	empty() {
		if ( this.uiTrackList ) {
			this.uiTrackList.empty();
		}
	},
	change( obj ) {
		if ( obj.tracks ) {
			this.uiTrackList.change( obj.tracks );
			this.uiTrackList.newRowElements.forEach( row => {
				row.firstChild.style.fontSize = this._pxPerBeat + "px";
				this._elGridCnt.append( row );
			} );
		}
	},
	resized() {
		var panelStyle = getComputedStyle( this._elPanel );

		this.width = this.rootElement.clientWidth;
		this._panelMinWidth = parseFloat( panelStyle.minWidth );
		this._panelMaxWidth = parseFloat( panelStyle.maxWidth ) || this.width;
		this._resizeGrid();
		this._updateGrid();
	},
	setFontSize( emPx ) {
		var tiny, curr = this._fontSize;

		emPx = ~~Math.min( Math.max( 16, emPx ), 256 );
		if ( emPx !== curr ) {
			tiny = emPx < 32;
			if ( tiny !== curr < 32 ) {
				this._elGridCnt.querySelectorAll( ".gsui-row" ).forEach( function( row ) {
					row.classList.toggle( "gs-row-tiny", tiny );
				} );
			}
			this._fontSize = emPx;
			this.rootElement.style.fontSize = emPx + "px";
		}
	},
	offset( offset, beatPx ) {
		this._timeOffset = offset;
		this._pxPerBeat = beatPx || this._pxPerBeat;
		this._updateGrid( !!beatPx );
	},
	timeSignature( a, b ) {
		this.uiTimeLine.timeSignature( a, b );
		this.uiBeatLines.timeSignature( a, b );
	},
	currentTime( beat ) {
		this.uiTimeLine.currentTime( beat );
		this.uiBeatLines.currentTime( beat );
	},
	loop( a, b ) {
		this.uiTimeLine.loop( a, b );
		this.uiBeatLines.loop( a, b );
	},
	panelWidth( width ) {
		width = Math.max( this._panelMinWidth, Math.min( width, this._panelMaxWidth ) );
		if ( this._timeOffset > 0 ) {
			this._timeOffset += ( width - this._panelWidth ) / this._pxPerBeat;
		}
		this._panelWidth = width;
		this._updatePanelSize();
	},
	contentY( yEm ) {
		var h = ( this.uiTrackList || this.uiKeys ).rootElement.clientHeight;

		h = Math.max( 0, h - this._elGrid.clientHeight ) / this._fontSize;
		this._contentY = yEm = Math.min( Math.max( 0, yEm ), h );
		this._elGridCnt.style.marginTop =
		this._elPanelCnt.style.marginTop = -yEm + "em";
	},
	loadKeys( from, nbOctaves ) {
		this._loadPanelCmp( "uiKeys", "uiTrackList" );
		this.uiKeys.octaves( from, nbOctaves );
		this.uiKeys.newRowElements.forEach( ( row, i ) => {
			row.firstChild.style.fontSize = this._pxPerBeat + "px";
			row.classList.toggle( "gs-row-tiny", this._fontSize < 32 );
			row.onmousedown = this._evmdRow.bind( this, row,
				from + nbOctaves - 1 - ~~( i / 12 ) );
			this._elGridCnt.append( row );
		} );
	},
	loadTrackList() {
		this._loadPanelCmp( "uiTrackList", "uiKeys" );
		this.uiTrackList.onchange = obj => this.onchange( {
			redo: { tracks: obj.redo },
			undo: { tracks: obj.undo }
		} );
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiGridSamples.template = gsuiGridSamples.template || this._init();
		div.appendChild( document.importNode( gsuiGridSamples.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},
	_init() {
		document.body.addEventListener( "mousemove", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmmRoot( e );
		} );
		document.body.addEventListener( "mouseup", function( e ) {
			gsuiGridSamples._focused && gsuiGridSamples._focused._evmuRoot( e );
		} );
		return document.getElementById( "gsuiGridSamples" );
	},
	_loadPanelCmp( cmpStr, oldCmpStr ) {
		var cmp = this[ cmpStr ],
			oldCmp = this[ oldCmpStr ];

		if ( oldCmp ) {
			oldCmp.remove();
			this.setFontSize( this._fontSize * ( cmpStr === "uiKeys" ? .5 : 2 ) );
			delete this[ oldCmpStr ];
		} else {
			this.setFontSize( cmpStr === "uiKeys" ? 20 : 40 );
		}
		if ( !cmp ) {
			this[ cmpStr ] = cmp = cmpStr === "uiKeys" ? new gsuiKeys() : new gsuiTrackList();
			this._elPanelCnt.prepend( cmp.rootElement );
		}
	},
	_resizeGrid() {
		this.uiTimeLine.resized();
		this.uiBeatLines.resized();
	},
	_contentScroll( e ) {
		this.contentY( this._contentY + ( 20 * ( e.deltaY > 0 ? 1 : -1 ) ) / this._fontSize );
	},
	_getMouseBeat( e ) {
		this._elGridCntBCR = this._elGridCnt.getBoundingClientRect();
		return this.uiTimeLine._round( ( e.pageX - this._elGridCntBCR.left ) / this._pxPerBeat );
	},
	_drawSelection( e ) {
		var sty = this._elSelection.style,
			left = this._mdBeat,
			width = this._getMouseBeat( e ) - left,
			top = Math.min( this._mdTrackBCR.top, this._mmTrackBCR.top ),
			bottom = Math.max( this._mdTrackBCR.bottom, this._mmTrackBCR.bottom );

		if ( width < 0 ) {
			width = -width;
			left -= width;
		}
		sty.left = left * this._pxPerBeat + "px";
		sty.width = width * this._pxPerBeat + "px";
		sty.top = top - this._elGridCntBCR.top + "px";
		sty.height = bottom - top + "px";
	},
	_updateGrid( beatPxChanged ) {
		var beatPx = this._pxPerBeat;

		this.uiTimeLine.offset( this._timeOffset, beatPx );
		this.uiBeatLines.offset( this._timeOffset, beatPx );
		this._timeOffset = this.uiTimeLine._offset;
		this._pxPerBeat = beatPx = this.uiTimeLine._pxPerBeat;
		this._elGridCnt.style.left = -this._timeOffset * beatPx + "px";
		if ( beatPxChanged ) {
			this._elGridCnt.querySelectorAll( ".gsui-row" ).forEach( function( row ) {
				row.firstChild.style.fontSize = beatPx + "px";
			} );
		}
	},
	_updatePanelSize() {
		this._elPanel.style.width =
		this._elGrid.style.left = this._panelWidth + "px";
		this.uiTimeLine.rootElement.style.left = this._panelWidth - 1 + "px";
		this._resizeGrid();
		this._updateGrid();
	},
	_findTrack( e ) {
		return this._elGridCnt.querySelectorAll( ".gsui-row" )[
			~~( ( e.pageY - this._elGridCntBCR.top ) / this._fontSize ) ]
	},
	_createBlock( obj, elRow ) {
		var uiBlock = new gsuiAudioBlock();

		uiBlock.when( obj.when );
		uiBlock.duration( obj.duration );
		if ( obj.key ) {
			uiBlock.datatype( "key" );
			uiBlock.name( obj.key );
		}
		elRow.firstChild.append( uiBlock.rootElement );
	},

	// events:
	_evocCurrentTime( beat ) {
		this.uiBeatLines.currentTime( beat );
		this.onchangeCurrentTime && this.onchangeCurrentTime( beat );
	},
	_evoiLoop( toggle, a, b ) {
		this.uiBeatLines.loop( toggle && a, b );
		this.oninputLoop && this.oninputLoop( toggle, a, b );
	},
	_evmdGrid( e ) {
		this._mdPageX = e.pageX;
		this._mdPageY = e.pageY;
		this._mdBeat = this._getMouseBeat( e );
		gsuiGridSamples._focused = this;
		if ( e.shiftKey ) {
			this._selectionStarting = true;
		} else if ( e.altKey ) {
			this._gridDragging = true;
			this._mouseOffset = this._timeOffset;
			this._mouseContentY = this._contentY;
		}
	},
	_evmdPanelEx( e ) {
		this._rootLeft = this.rootElement.getBoundingClientRect().left;
		this._panelResizing = this._elPanelExt.clientWidth - e.layerX;
		this._elPanelExt.classList.add( "gsui-hover" );
		gsuiGridSamples._focused = this;
	},
	_evmdRow( elRow, octave, e ) {
		if ( !e.shiftKey && !e.ctrlKey && !e.altKey ) {
			if ( e.button === 0 ) {
				this._createBlock( {
					when: this._getMouseBeat( e ),
					offset: 0,
					duration: 1,
					key: elRow.dataset.key + octave
				}, elRow );
			} else if ( e.button === 2 ) {
				// ...
			}
		}
	},
	_evowGrid( e ) {
		if ( !e.shiftKey && !e.ctrlKey ) {
			this._contentScroll( e );
		} else {
			var layerX, offInc, beatPx = this._pxPerBeat;

			if ( e.ctrlKey ) {
				layerX = e.pageX - this._elGrid.getBoundingClientRect().left;
				beatPx = Math.min( Math.max( 8, beatPx * ( e.deltaY > 0 ? .9 : 1.1 ) ), 512 );
				offInc = ( layerX / this._pxPerBeat * ( beatPx - this._pxPerBeat ) ) / beatPx;
			} else {
				offInc = ( e.deltaY > 0 ? 20 : -20 ) / beatPx;
			}
			this.offset( Math.max( 0, this._timeOffset + offInc ),
				e.ctrlKey ? beatPx : undefined );
		}
		return false;
	},
	_evowPanel( e ) {
		if ( e.ctrlKey ) {
			var layerY = e.pageY - this._elPanel.getBoundingClientRect().top,
				oldFs = this._fontSize,
				fs = oldFs * ( e.deltaY > 0 ? .9 : 1.1 );

			this.setFontSize( fs );
			fs = this._fontSize;
			this.contentY( this._contentY + ( layerY / oldFs * ( fs - oldFs ) ) / fs );
		} else if ( !e.shiftKey ) {
			this._contentScroll( e );
		}
		return false;
	},
	_evmmRoot( e ) {
		var pxRel = e.pageX - this._mdPageX,
			pyRel = e.pageY - this._mdPageY;

		if ( this._gridDragging ) {
			this.offset( this._mouseOffset - pxRel / this._pxPerBeat, this._pxPerBeat );
			this.contentY( this._mouseContentY - pyRel / this._fontSize );
		} else if ( this._panelResizing != null ) {
			this.panelWidth( e.pageX - this._rootLeft + this._panelResizing );
		} else if ( this._selectionStarted ) {
			this._mmTrackBCR = this._findTrack( e ).getBoundingClientRect();
			this._drawSelection( e );
		} else if ( this._selectionStarting ) {
			if ( Math.max( Math.abs( pxRel ), Math.abs( pyRel ) ) > 6 ) {
				this._mdTrackBCR =
				this._mmTrackBCR = this._findTrack( e ).getBoundingClientRect();
				this._drawSelection( e );
				this._elSelection.classList.remove( "hidden" );
				this._selectionStarted = true;
				delete this._selectionStarting;
			}
		}
	},
	_evmuRoot( e ) {
		this._elPanelExt.classList.remove( "gsui-hover" );
		this._elSelection.classList.add( "hidden" );
		delete this._gridDragging;
		delete this._selectionStarted;
		delete this._selectionStarting;
		delete this._panelResizing;
		delete gsuiGridSamples._focused;
	}
};
<|endoftext|>


<commit_before>/*
This component is the map view. It shows the user the possible routes he/she can take to arrive at the destination
*/

var React = require('react');
var RouteDetailView = require('./routeDetailView');
var ListView = require('./listView');
var MapHelpers = require('./mapHelpers');
var ToolView = require('./toolView');

/***************
****** MUI *****
****************/
var mui = require('material-ui');
var ThemeManager = new mui.Styles.ThemeManager();
var {Card, CardHeader, CardMedia, CardActions, CardText, Avatar, CardTitle} = mui;

var MapView = React.createClass({
  // adds access to the router context. the getCurrentParams method can then be used to get the properties from the route
  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState () {
    return {
      routes: [],
      markers: {},
      currentRoute: { wayPoints: [], results: [] }, //default values for currentRoute
      searchRadius: this.defaultOptions.radius
    }
  },
  //default options to be used for this view, inclusind route options and radius of search
  defaultOptions: {
    polyline: { //configuration for polylines (inactive ones)
      zIndex: 1,
      strokeOpacity: 0.4,
      strokeWeight: 4
    },
    radius: 5 // radius used to generate wayPoints, in km.
  },
  // this is called after the first render of the component
  componentDidMount () {
    var {origin, destination} = this.context.router.getCurrentParams();

    var start = this.getLatLong(origin);
    var end = this.getLatLong(destination);

    var map = this.initializeMap(start);
    this.setState({
      map
    });

    this.calcRoute(start, end, map);

    var bounds = new google.maps.LatLngBounds();
    bounds.extend(start);
    bounds.extend(end);
    map.fitBounds(bounds);
  }, //componentDidMount()
  // Going to
  shouldComponentUpdate (nextProps, nextState) {
    var results = nextState.currentRoute.results;
    if(results){
      this.updateMapMarkers(results);
    } //if

    return true;
  }, //shouldComponentUpdate()
  // turns a lat/long string into a google maps LatLong Object
  getLatLong (location) {
    return new google.maps.LatLng(location.split(',')[0], location.split(',')[1]);
  },

  // initializes a map and attaches it to the map div
  initializeMap (center) {
    var mapOptions = {
      zoom: 10,
      center,
    };
    return new google.maps.Map(document.getElementById('map'), mapOptions);
  },
  // Print new markers
  updateMapMarkers(results){
    var map = this.state.map;
    var markers = this.state.markers; //array of
    var component = this;

    results.forEach(function(venue, index){
      var {lng, lat} = venue.location;

      //create new marker
      if(!markers[venue.id]){ //
        var position = new google.maps.LatLng(lat, lng);

        var marker = new google.maps.Marker({
          position: position,
        });

        // create custom infowindow
        // NOTE: we can also add rating color to decorate marker
        var infowindow = new google.maps.InfoWindow({
          content: venue.name + "
 Rating: "+venue.rating
        });

        //create event listener to open info window
        google.maps.event.addListener(marker, 'mouseover', function() {
          infowindow.open(map, this);
        }); //mouseover

        // create event listener to close info window
        google.maps.event.addListener(marker, 'mouseout', function() {
          infowindow.close();
        }); //mouseout

        // create event listener to close info window
        google.maps.event.addListener(marker, 'click', function() {
          component.openFourSquare(venue);
        }); //mouseout

        //show map marker
        marker.setMap(map);
        // add current marker to state
        component.state.markers[venue.id] = marker;
        // component.state.markers.push(marker);
      } //if

      //display markers
    }); //forEach
  }, //updateMapMarkers()

  // clear map markers
  clearMapMarkers (markers){
    this.state.markers = {};

    for(var key in markers){
      var marker = markers[key];
      marker.setMap(null);
    } //for
  }, //clearMapMarkers

  // set the current selected route
  setCurrentRoute (index) {
    var newRoute = this.state.routes[index];
    // clear previously active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions(this.defaultOptions.polyline);
    } //if

    //clear previously displayed map markers
    this.clearMapMarkers(this.state.markers);

    var wayPoints = this.updateWayPoints(newRoute);
    console.log(' &&&&&&&&& before this.setState');
    this.setState({
      wayPoints,
      currentRoute: newRoute
    });
  },

  // this creates a directions route from the start point to the end point
  calcRoute (start, end, map) {
    var directionsService = new google.maps.DirectionsService();
    var component = this;

    // create markers
    new google.maps.Marker({
      position: start,
      map,
      label: 'A'
    });
    new google.maps.Marker({
      position: end,
      map,
      label: 'B'
    });

    var request = {
      origin:start,
      destination:end,
      travelMode: google.maps.TravelMode.DRIVING,
      provideRouteAlternatives: true,
    }; //request

    // make a directios request to the maps API
    directionsService.route(request, function (response, status) {
      if (status == google.maps.DirectionsStatus.OK) { //.OK indicates the response contains a valid DirectionsResult.
        console.log(response);
        var routes = [];
        var colors = ['blue', 'black', 'green', 'pink'];

        for (var i = 0, len = response.routes.length; i < len; i++) {
          // create a polyline for each suggested route
          var polyLine = new google.maps.Polyline({
            path: response.routes[i].overview_path,
            strokeColor: colors[i],
            map
          });

          // add properties to each polyline
          polyLine.path = response.routes[i].overview_path;
          polyLine.color = colors[i];
          polyLine.distance = response.routes[i].legs[0].distance.text;
          polyLine.distanceMeters = response.routes[i].legs[0].distance.value;
          polyLine.duration = response.routes[i].legs[0].duration.text;
          polyLine.wayPoints = [];
          polyLine.results = [];

          polyLine.setOptions(component.defaultOptions.polyline);
          // save polylines for later use
          routes.push(polyLine);

          // add event listener to update the route on click
          polyLine.addListener('click', component.setCurrentRoute.bind(component, i));

        } //for(each route)

        var wayPoints = component.updateWayPoints(routes[0]); //initialize with first route
        routes[0].wayPoints = wayPoints;
        var searchRadius = component.state.searchRadius;
        component.setState({
          currentRoute: routes[0], // on the initial load make the first suggestion active
          routes
        });
      } // if
    }); //directionsService.route callback

  }, //calcRoutes()

  // updates wayPoints if available, create wayPoints if not
  updateWayPoints (newRoute){
    //lazy-load currentRoute wayPoints, and save it to currentRoute object when complete
    var wayPoints =  newRoute.wayPoints.length>1 ? newRoute.wayPoints : this.createWayPoints(newRoute); //only create new wayPoints if hasn't been done before
    this.displayWayPoints(newRoute.wayPoints);

    return wayPoints;
  }, // updateWayPoints()

  // creates wayPoints for new route. Only executes once per route, and becomes saved.
  createWayPoints (newRoute) {

    var radius = this.defaultOptions.radius; //default radius
    var minRadiusToDistanceFactor = 5;

    var distance = newRoute.distanceMeters/1000;
    if (distance < minRadiusToDistanceFactor*radius) {
      radius = distance/minRadiusToDistanceFactor;
      this.state.searchRadius = radius; // do not set off re-render here
    }

    var path = newRoute.path; // get path from target route
    var map = this.state.map; // note: map is a state of this view

    var wayPoints = [];
    var lastWayPoint;

    path.forEach(function(point, index) {
      // calculate cumulative distance from start, in meters
      if (index === 0) {
        point.distance = 0;
      } else {
        var prevPoint = path[index-1];
        point.distance = prevPoint.distance + MapHelpers.getDistanceBetweenPoints(prevPoint, point)*1000;
      }

      // add first point
      if (!lastWayPoint) {
        wayPoints.push(point);
        lastWayPoint = point;
      }
      // add an inbetween point if the distance is too big
      if (MapHelpers.getDistanceBetweenPoints(lastWayPoint, point) > 1.5 * radius) {
        var middlePoint = MapHelpers.getMiddlePoint(lastWayPoint, point);
        middlePoint.distance = prevPoint.distance + MapHelpers.getDistanceBetweenPoints(prevPoint, middlePoint)*1000;
        wayPoints.push(middlePoint);
      }

      // add new point if the distance is larger than the radius
      if (MapHelpers.getDistanceBetweenPoints(lastWayPoint, point) > radius) {
        wayPoints.push(point);
        lastWayPoint = point;
      }
    });

    newRoute.wayPoints = wayPoints; //save to the currentRoute object
    return wayPoints;

  }, //createWayPoints()

  //display wayPoints on the map
  displayWayPoints(wayPoints){
    wayPoints.forEach(function(point) {
      new google.maps.Circle({
        center: point,
        map: this.state.map,
        radius: this.state.searchRadius * 1000,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35,
      });
    }.bind(this));
  }, //displayWayPoints()

  // prop for ListView. Allows it to add results to the currentRoute
  updateResults (results) {
    this.state.currentRoute.results = results;
    this.setState({}); //forces re-render (e.g. for the listView)
  }, //updateResults()

  // have left-container switch to detailView
  routeToHome(){
    window.reactRouter.transitionTo('home');
  },

  openFourSquare (venue){
    var url = "https://foursquare.com/v/"+escape(venue.name)+"/"+venue.id;
    console.log("TEST inside openFourSquare. url="+url);
    window.open(url);
  },

  render () {
    // update display of active route
    if (this.state.currentRoute.setOptions) {
      this.state.currentRoute.setOptions({
        zIndex: 2,
        strokeOpacity: 1,
      });
    };

    return (

              <ToolView
                routeToHome={this.routeToHome}
              /> {/* ToolView */}

                <ListView
                  searchRadius={this.state.searchRadius}
                  currentRoute={this.state.currentRoute}
                  updateResults={this.updateResults}
                  openFourSquare = {this.openFourSquare}
                /> {/* ListView*/}

 {/* list-container */}

 {/* col-sm-4 */}

 {/* row */}

              <RouteDetailView
                routes={this.state.routes}
                setCurrentRoute={this.setCurrentRoute}
              /> {/* RouteDetailView */}

 {/* row */}

 {/* col-sm-8 */}

 {/* row */}

    )
  }
});

module.exports = MapView;
<commit_msg>(feat) thickened polylines<commit_after>/*
This component is the map view. It shows the user the possible routes he/she can take to arrive at the destination
*/

var React = require('react');
var RouteDetailView = require('./routeDetailView');
var ListView = require('./listView');
var MapHelpers = require('./mapHelpers');
var ToolView = require('./toolView');

/***************
****** MUI *****
****************/
var mui = require('material-ui');
var ThemeManager = new mui.Styles.ThemeManager();
var {Card, CardHeader, CardMedia, CardActions, CardText, Avatar, CardTitle} = mui;

var MapView = React.createClass({
  // adds access to the router context. the getCurrentParams method can then be used to get the properties from the route
  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState () {
    return {
      routes: [],
      markers: {},
      currentRoute: { wayPoints: [], results: [] }, //default values for currentRoute
      searchRadius: this.defaultOptions.radius
    }
  },
  //default options to be used for this view, inclusind route options and radius of search
  defaultOptions: {
    polyline: { //configuration for polylines (inactive ones)
      zIndex: 1,
      strokeOpacity: 0.4,
      strokeWeight: 6
    },
    radius: 5, // radius used to generate wayPoints, in km.
    routePalette: ['blue', 'black', 'green', 'pink']
  },
  // this is called after the first render of the component
  componentDidMount () {
    var {origin, destination} = this.context.router.getCurrentParams();

    var start = this.getLatLong(origin);
    var end = this.getLatLong(destination);

    var map = this.initializeMap(start);
    this.setState({
      map
    });

    this.calcRoute(start, end, map);

    var bounds = new google.maps.LatLngBounds();
    bounds.extend(start);
    bounds.extend(end);
    map.fitBounds(bounds);
  }, //componentDidMount()
  // Going to
  shouldComponentUpdate (nextProps, nextState) {
    var results = nextState.currentRoute.results;
    if(results){
      this.updateMapMarkers(results);
    } //if

    return true;
  }, //shouldComponentUpdate()
  // turns a lat/long string into a google maps LatLong Object
  getLatLong (location) {
    return new google.maps.LatLng(location.split(',')[0], location.split(',')[1]);
  },

  // initializes a map and attaches it to the map div
  initializeMap (center) {
    var mapOptions = {
      zoom: 10,
      center,
    };
    return new google.maps.Map(document.getElementById('map'), mapOptions);
  },
  // Print new markers
  updateMapMarkers(results){
    var map = this.state.map;
    var markers = this.state.markers; //array of
    var component = this;

    results.forEach(function(venue, index){
      var {lng, lat} = venue.location;

      //create new marker
      if(!markers[venue.id]){ //
        var position = new google.maps.LatLng(lat, lng);

        var marker = new google.maps.Marker({
          position: position,
        });

        // create custom infowindow
        // NOTE: we can also add rating color to decorate marker
        var infowindow = new google.maps.InfoWindow({
          content: venue.name + "
 Rating: "+venue.rating
        });

        //create event listener to open info window
        google.maps.event.addListener(marker, 'mouseover', function() {
          infowindow.open(map, this);
        }); //mouseover

        // create event listener to close info window
        google.maps.event.addListener(marker, 'mouseout', function() {
          infowindow.close();
        }); //mouseout

        // create event listener to close info window
        google.maps.event.addListener(marker, 'click', function() {
          component.openFourSquare(venue);
        }); //mouseout

        //show map marker
        marker.setMap(map);
        // add current marker to state
        component.state.markers[venue.id] = marker;
        // component.state.markers.push(marker);
      } //if

      //display markers
    }); //forEach
  }, //updateMapMarkers()

  // clear map markers
  clearMapMarkers (markers){
    this.state.markers = {};

    for(var key in markers){
      var marker = markers[key];
      marker.setMap(null);
    } //for
  }, //clearMapMarkers

  // set the current selected route
  setCurrentRoute (index) {
    var newRoute = this.state.routes[index];
    // clear previously active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions(this.defaultOptions.polyline);
    } //if

    //clear previously displayed map markers
    this.clearMapMarkers(this.state.markers);

    var wayPoints = this.updateWayPoints(newRoute);
    console.log(' &&&&&&&&& before this.setState');
    this.setState({
      wayPoints,
      currentRoute: newRoute
    });
  },

  // this creates a directions route from the start point to the end point
  calcRoute (start, end, map) {
    var directionsService = new google.maps.DirectionsService();
    var component = this;

    // create markers
    new google.maps.Marker({
      position: start,
      map,
      label: 'A'
    });
    new google.maps.Marker({
      position: end,
      map,
      label: 'B'
    });

    var request = {
      origin:start,
      destination:end,
      travelMode: google.maps.TravelMode.DRIVING,
      provideRouteAlternatives: true,
    }; //request

    // make a directios request to the maps API
    directionsService.route(request, function (response, status) {
      if (status == google.maps.DirectionsStatus.OK) { //.OK indicates the response contains a valid DirectionsResult.
        console.log(response);
        var routes = [];
        var colors = component.defaultOptions.routePalette;

        for (var i = 0, len = response.routes.length; i < len; i++) {
          // create a polyline for each suggested route
          var polyLine = new google.maps.Polyline({
            path: response.routes[i].overview_path,
            strokeColor: colors[i],
            map
          });

          // add properties to each polyline
          polyLine.path = response.routes[i].overview_path;
          polyLine.color = colors[i];
          polyLine.distance = response.routes[i].legs[0].distance.text;
          polyLine.distanceMeters = response.routes[i].legs[0].distance.value;
          polyLine.duration = response.routes[i].legs[0].duration.text;
          polyLine.wayPoints = [];
          polyLine.results = [];

          polyLine.setOptions(component.defaultOptions.polyline);
          // save polylines for later use
          routes.push(polyLine);

          // add event listener to update the route on click
          polyLine.addListener('click', component.setCurrentRoute.bind(component, i));

        } //for(each route)

        var wayPoints = component.updateWayPoints(routes[0]); //initialize with first route
        routes[0].wayPoints = wayPoints;
        var searchRadius = component.state.searchRadius;
        component.setState({
          currentRoute: routes[0], // on the initial load make the first suggestion active
          routes
        });
      } // if
    }); //directionsService.route callback

  }, //calcRoutes()

  // updates wayPoints if available, create wayPoints if not
  updateWayPoints (newRoute){
    //lazy-load currentRoute wayPoints, and save it to currentRoute object when complete
    var wayPoints =  newRoute.wayPoints.length>1 ? newRoute.wayPoints : this.createWayPoints(newRoute); //only create new wayPoints if hasn't been done before
    this.displayWayPoints(newRoute.wayPoints);

    return wayPoints;
  }, // updateWayPoints()

  // creates wayPoints for new route. Only executes once per route, and becomes saved.
  createWayPoints (newRoute) {

    var radius = this.defaultOptions.radius; //default radius
    var minRadiusToDistanceFactor = 5;

    var distance = newRoute.distanceMeters/1000;
    if (distance < minRadiusToDistanceFactor*radius) {
      radius = distance/minRadiusToDistanceFactor;
      this.state.searchRadius = radius; // do not set off re-render here
    }

    var path = newRoute.path; // get path from target route
    var map = this.state.map; // note: map is a state of this view

    var wayPoints = [];
    var lastWayPoint;

    path.forEach(function(point, index) {
      // calculate cumulative distance from start, in meters
      if (index === 0) {
        point.distance = 0;
      } else {
        var prevPoint = path[index-1];
        point.distance = prevPoint.distance + MapHelpers.getDistanceBetweenPoints(prevPoint, point)*1000;
      }

      // add first point
      if (!lastWayPoint) {
        wayPoints.push(point);
        lastWayPoint = point;
      }
      // add an inbetween point if the distance is too big
      if (MapHelpers.getDistanceBetweenPoints(lastWayPoint, point) > 1.5 * radius) {
        var middlePoint = MapHelpers.getMiddlePoint(lastWayPoint, point);
        middlePoint.distance = prevPoint.distance + MapHelpers.getDistanceBetweenPoints(prevPoint, middlePoint)*1000;
        wayPoints.push(middlePoint);
      }

      // add new point if the distance is larger than the radius
      if (MapHelpers.getDistanceBetweenPoints(lastWayPoint, point) > radius) {
        wayPoints.push(point);
        lastWayPoint = point;
      }
    });

    newRoute.wayPoints = wayPoints; //save to the currentRoute object
    return wayPoints;

  }, //createWayPoints()

  //display wayPoints on the map
  displayWayPoints(wayPoints){
    wayPoints.forEach(function(point) {
      new google.maps.Circle({
        center: point,
        map: this.state.map,
        radius: this.state.searchRadius * 1000,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35,
      });
    }.bind(this));
  }, //displayWayPoints()

  // prop for ListView. Allows it to add results to the currentRoute
  updateResults (results) {
    this.state.currentRoute.results = results;
    this.setState({}); //forces re-render (e.g. for the listView)
  }, //updateResults()

  // have left-container switch to detailView
  routeToHome(){
    window.reactRouter.transitionTo('home');
  },

  openFourSquare (venue){
    var url = "https://foursquare.com/v/"+escape(venue.name)+"/"+venue.id;
    console.log("TEST inside openFourSquare. url="+url);
    window.open(url);
  },

  render () {
    // update display of active route
    if (this.state.currentRoute.setOptions) {
      this.state.currentRoute.setOptions({
        zIndex: 2,
        strokeOpacity: 1,
      });
    };

    return (

              <ToolView
                routeToHome={this.routeToHome}
              /> {/* ToolView */}

                <ListView
                  searchRadius={this.state.searchRadius}
                  currentRoute={this.state.currentRoute}
                  updateResults={this.updateResults}
                  openFourSquare = {this.openFourSquare}
                /> {/* ListView*/}

 {/* list-container */}

 {/* col-sm-4 */}

 {/* row */}

              <RouteDetailView
                routes={this.state.routes}
                setCurrentRoute={this.setCurrentRoute}
              /> {/* RouteDetailView */}

 {/* row */}

 {/* col-sm-8 */}

 {/* row */}

    )
  }
});

module.exports = MapView;
<|endoftext|>


<commit_before>var main = function () {
    "use strict";

    document.cookie="paul's cookie is here";

    var goTwoBoard = false;
    var theMainGoConfigObject;
    var goUi;
    var goContainer;

    runPrelude();

    function runPrelude () {
        var root = new RootObject();
        var html = new GoHtmlObject(root, goTwoBoard);
        root.setHtmlObject(html);
        html.createPreludeHolder();
        $(".prelude_holder button").on("click", function() {
            root.setMyName($(".prelude_holder input").val());
            root.setLanguageUsed($(".prelude_holder select").val());
            console.log("runPrelude() ", "name=" + root.myName() + " language=" + root.languageUsed());
            if (root.myName()) {
                root.setupLink();
                runCreateSession(root);
            }
        });
    }

    function runCreateSession (root_val) {
        var session = new SessionObject(root_val);
        runGoConfig(session);
    }

    function runGoConfig (session_val) {
        theMainGoConfigObject = new GoConfigObject(session_val.rootObject().myName());
        var config = theMainGoConfigObject;
        session_val.rootObject().htmlObject().createConfigHolders();
        $(".config_holder button").on("click", function() {
            config.setBoardSize($(".board_size_section select").val());
            config.setMyColor($(".play_color_section select").val());
            config.setKomiPoint($(".komi_section select").val());
            config.setHandicapPoint($(".handicap_section select").val());
            config.setOpponentName($(".opponent_section select").val());
            if (config.opponentName() === "Myself") {
                config.setOpponentName(session_val.rootObject().myName());
            }
            console.log("runConfig() ", "opponent=" + config.opponentName() + " board_size=" + theMainGoConfigObject.boardSize() +
                            " color=" + config.myColor() +
                            " komi=" + config.komiPoint() +
                            " handicap=" + config.handicapPoint());
            if (config.opponentName()) {
                session_val.setHisName(config.opponentName());
                runGoGame(session_val);
            }
        });
    }

    function runGoGame (session_val) {
        session_val.rootObject().htmlObject().createPlayHolders();
        goUi = new GoUiObject("goCanvas");
        goContainer = new GoContainerObject(session_val, theMainGoConfigObject, goUi, "1");
        goUi.initElements();
        goUi.drawBoard(goContainer.engineObject());

        var addCommentFromInputBox = function () {
            var $new_comment = $("<p>");
            if ($(".comment-input input").val() !== "") {
                $new_comment.text($(".comment-input input").val());
                $new_comment.hide();
                $(".comments").append($new_comment);
                $new_comment.fadeIn();
                $(".comment-input input").val("");
            }
        };

        $(".comment-input button").on("click", function(event) {
            addCommentFromInputBox();
        });

        $(".comment-input input").on("keypress", function(event) {
            if (event.keyCode == 13) {
                addCommentFromInputBox();
            }
        });

        $("canvas").on("click", function(event) {
            goUi.uiClickApi(event.clientX, event.clientY);
            if (goContainer2) {
                goUi2.uiClickApi(event.clientX, event.clientY);
            }
        });
        $("canvas").on("mousemove", function(event) {
            goUi.uiMouseMove(event.clientX, event.clientY);
            if (goContainer2) {
                goUi2.uiMouseMove(event.clientX, event.clientY);
            }
        });

        if (goTwoBoard) {
            var goUi2 = new GoUiObject("goCanvas2");
            var goConfig2 = theMainGoConfigObject.createTwoBoardOpponentConfig();
            var goContainer2 = new GoContainerObject(session_val.rootObject(), goConfig2, goUi2, "2");
            goUi2.initElements();
            goUi2.drawBoard(goContainer2.engineObject());

            goContainer2.setHisContainerObject(goContainer);
            goContainer.setHisContainerObject(goContainer2);
        }
    }
};

$(document).ready(main);

<commit_msg>container<commit_after>var main = function () {
    "use strict";

    document.cookie="paul's cookie is here";

    var goTwoBoard = false;
    var theMainGoConfigObject;
    var goUi;
    var goContainer;

    runPrelude();

    function runPrelude () {
        var root = new RootObject();
        var html = new GoHtmlObject(root, goTwoBoard);
        root.setHtmlObject(html);
        html.createPreludeHolder();
        $(".prelude_holder button").on("click", function() {
            root.setMyName($(".prelude_holder input").val());
            root.setLanguageUsed($(".prelude_holder select").val());
            console.log("runPrelude() ", "name=" + root.myName() + " language=" + root.languageUsed());
            if (root.myName()) {
                root.setupLink();
                runCreateSession(root);
            }
        });
    }

    function runCreateSession (root_val) {
        var session = new SessionObject(root_val);
        runGoConfig(session);
    }

    function runGoConfig (session_val) {
        theMainGoConfigObject = new GoConfigObject(session_val.rootObject().myName());
        var config = theMainGoConfigObject;
        session_val.rootObject().htmlObject().createConfigHolders();
        $(".config_holder button").on("click", function() {
            config.setBoardSize($(".board_size_section select").val());
            config.setMyColor($(".play_color_section select").val());
            config.setKomiPoint($(".komi_section select").val());
            config.setHandicapPoint($(".handicap_section select").val());
            config.setOpponentName($(".opponent_section select").val());
            if (config.opponentName() === "Myself") {
                config.setOpponentName(session_val.rootObject().myName());
            }
            console.log("runConfig() ", "opponent=" + config.opponentName() + " board_size=" + theMainGoConfigObject.boardSize() +
                            " color=" + config.myColor() +
                            " komi=" + config.komiPoint() +
                            " handicap=" + config.handicapPoint());
            if (config.opponentName()) {
                session_val.setHisName(config.opponentName());
                goUi = new GoUiObject("goCanvas");
                goContainer = new GoContainerObject(session_val, config, goUi, "1");
                runGoGame(session_val);
            }
        });
    }

    function runGoGame (session_val) {
        session_val.rootObject().htmlObject().createPlayHolders();
        goUi.initElements();
        goUi.drawBoard(goContainer.engineObject());

        var addCommentFromInputBox = function () {
            var $new_comment = $("<p>");
            if ($(".comment-input input").val() !== "") {
                $new_comment.text($(".comment-input input").val());
                $new_comment.hide();
                $(".comments").append($new_comment);
                $new_comment.fadeIn();
                $(".comment-input input").val("");
            }
        };

        $(".comment-input button").on("click", function(event) {
            addCommentFromInputBox();
        });

        $(".comment-input input").on("keypress", function(event) {
            if (event.keyCode == 13) {
                addCommentFromInputBox();
            }
        });

        $("canvas").on("click", function(event) {
            goUi.uiClickApi(event.clientX, event.clientY);
            if (goContainer2) {
                goUi2.uiClickApi(event.clientX, event.clientY);
            }
        });
        $("canvas").on("mousemove", function(event) {
            goUi.uiMouseMove(event.clientX, event.clientY);
            if (goContainer2) {
                goUi2.uiMouseMove(event.clientX, event.clientY);
            }
        });

        if (goTwoBoard) {
            var goUi2 = new GoUiObject("goCanvas2");
            var goConfig2 = theMainGoConfigObject.createTwoBoardOpponentConfig();
            var goContainer2 = new GoContainerObject(session_val.rootObject(), goConfig2, goUi2, "2");
            goUi2.initElements();
            goUi2.drawBoard(goContainer2.engineObject());

            goContainer2.setHisContainerObject(goContainer);
            goContainer.setHisContainerObject(goContainer2);
        }
    }
};

$(document).ready(main);

<|endoftext|>


<commit_before>var main = function () {
    "use strict";

    document.cookie="paul's cookie is here";
    runPrelude();

    function runPrelude () {
        var root = new RootObject();
        root.htmlObject().createPreludeHolder();
        $(".prelude_holder button").on("click", function() {
            root.setMyName($(".prelude_holder input").val());
            root.setLanguageUsed($(".prelude_holder select").val());
            console.log("runPrelude() ", "name=" + root.myName() + " language=" + root.languageUsed());
            if (root.myName()) {
                root.ajaxObject().setupLink(setupLinkCallback, root);
            }
        });
    }

    function setupLinkCallback (root_val) {
        root_val.ajaxObject().getNameList(getNameListCallback, root_val);
    }

    var get_name_list_done = false;
    var run_create_session_caller = false;

    function getNameListCallback (root_val) {
        if (get_name_list_done) {
            return;
        }

        //root_val.ajaxObject().getNameList(getNameListCallback, root_val);

        if (!run_create_session_caller) {
            runCreateSession(root_val);
            run_create_session_caller = true;
        }
    }

    function runCreateSession (root_val) {
        var session = new SessionObject(root_val);
        session.rootObject().htmlObject().createSessionHolders(root_val);
        $(".session_holder button").on("click", function() {
            session.setHisName($(".peer_section select").val());
            console.log("runCreateSession() ", "peer_name=" + session.hisName());
            session.ajaxObject().initiateSessionConnection(setupSessionCallback, session);
        });
    }

    function setupSessionCallback (session_val) {
        get_name_list_done = true;
        runGoConfig(session_val);
    }

    function runGoConfig (session_val) {
        var config = new GoConfigObject(session_val);
        session_val.rootObject().htmlObject().createConfigHolders();
        $(".config_holder button").on("click", function() {
            config.setBoardSize($(".board_size_section select").val());
            config.setMyColor($(".play_color_section select").val());
            config.setKomiPoint($(".komi_section select").val());
            config.setHandicapPoint($(".handicap_section select").val());
            console.log("runConfig() ", " board_size=" + config.boardSize() +
                            " color=" + config.myColor() +
                            " komi=" + config.komiPoint() +
                            " handicap=" + config.handicapPoint());
            runGoGame(session_val, config);
        });
    }

    function runGoGame (session_val, config_val) {
        var container = new GoContainerObject(session_val, config_val);
        container.rootObject().htmlObject().createPlayHolders();
        container.uiObject().initElements();
        container.uiObject().drawBoard(container.engineObject());

        $("canvas").on("click", function(event) {
            container.uiObject().uiClickApi(event.clientX, event.clientY);
        });

        $("canvas").on("mousemove", function(event) {
            container.uiObject().uiMouseMove(event.clientX, event.clientY);
        });

        var addCommentFromInputBox = function () {
            var $new_comment = $("<p>");
            if ($(".comment-input input").val() !== "") {
                $new_comment.text($(".comment-input input").val());
                $new_comment.hide();
                $(".comments").append($new_comment);
                $new_comment.fadeIn();
                $(".comment-input input").val("");
            }
        };

        $(".comment-input button").on("click", function(event) {
            addCommentFromInputBox();
        });

        $(".comment-input input").on("keypress", function(event) {
            if (event.keyCode == 13) {
                addCommentFromInputBox();
            }
        });
    }
};

$(document).ready(main);

<commit_msg>name list<commit_after>var main = function () {
    "use strict";

    document.cookie="paul's cookie is here";
    runPrelude();

    function runPrelude () {
        var root = new RootObject();
        root.htmlObject().createPreludeHolder();
        $(".prelude_holder button").on("click", function() {
            root.setMyName($(".prelude_holder input").val());
            root.setLanguageUsed($(".prelude_holder select").val());
            console.log("runPrelude() ", "name=" + root.myName() + " language=" + root.languageUsed());
            if (root.myName()) {
                root.ajaxObject().setupLink(setupLinkCallback, root);
            }
        });
    }

    function setupLinkCallback (root_val) {
        root_val.ajaxObject().getNameList(getNameListCallback, root_val);
    }

    var run_create_session_caller = false;
    function getNameListCallback (root_val) {
        if (!run_create_session_caller) {
            runCreateSession(root_val);
            run_create_session_caller = true;
        }
    }

    function runCreateSession (root_val) {
        var session = new SessionObject(root_val);
        session.rootObject().htmlObject().createSessionHolders(root_val);
        $(".session_holder button").on("click", function() {
            session.setHisName($(".peer_section select").val());
            console.log("runCreateSession() ", "peer_name=" + session.hisName());
            session.ajaxObject().initiateSessionConnection(setupSessionCallback, session);
        });
    }

    function setupSessionCallback (session_val) {
        runGoConfig(session_val);
    }

    function runGoConfig (session_val) {
        var config = new GoConfigObject(session_val);
        session_val.rootObject().htmlObject().createConfigHolders();
        $(".config_holder button").on("click", function() {
            config.setBoardSize($(".board_size_section select").val());
            config.setMyColor($(".play_color_section select").val());
            config.setKomiPoint($(".komi_section select").val());
            config.setHandicapPoint($(".handicap_section select").val());
            console.log("runConfig() ", " board_size=" + config.boardSize() +
                            " color=" + config.myColor() +
                            " komi=" + config.komiPoint() +
                            " handicap=" + config.handicapPoint());
            runGoGame(session_val, config);
        });
    }

    function runGoGame (session_val, config_val) {
        var container = new GoContainerObject(session_val, config_val);
        container.rootObject().htmlObject().createPlayHolders();
        container.uiObject().initElements();
        container.uiObject().drawBoard(container.engineObject());

        $("canvas").on("click", function(event) {
            container.uiObject().uiClickApi(event.clientX, event.clientY);
        });

        $("canvas").on("mousemove", function(event) {
            container.uiObject().uiMouseMove(event.clientX, event.clientY);
        });

        var addCommentFromInputBox = function () {
            var $new_comment = $("<p>");
            if ($(".comment-input input").val() !== "") {
                $new_comment.text($(".comment-input input").val());
                $new_comment.hide();
                $(".comments").append($new_comment);
                $new_comment.fadeIn();
                $(".comment-input input").val("");
            }
        };

        $(".comment-input button").on("click", function(event) {
            addCommentFromInputBox();
        });

        $(".comment-input input").on("keypress", function(event) {
            if (event.keyCode == 13) {
                addCommentFromInputBox();
            }
        });
    }
};

$(document).ready(main);

<|endoftext|>


<commit_before>var ClimbingGrade=function(){function e(e,i,t){this._inputGrade=e,this._inputSystemName=i,this._rangeDelimeter=t&&t.rangeDelimeter?t.rangeDelimeter:" to ",this._pairDelimeter=t&&t.pairDelimeter?t.pairDelimeter:"/",this._systems={yds:{grades:["5.1","5.2","5.3","5.4","5.5","5.6","5.7","5.8","5.9","5.10a","5.10b","5.10c","5.10d","5.11a","5.11b","5.11c","5.11d","5.12a","5.12b","5.12c","5.12d","5.13a","5.13b","5.13c","5.13d","5.14a","5.14b","5.14c","5.14d","5.15a","5.15b","5.15c","5.15d"]},french:{grades:["2","2+","3","3+","4","4+","5a","5b","5c","6a","6a+","6b","6b+","6c","6c/6c+","6c+","7a","7a+","7b","7b+","7c","7c+","8a","8a+","8b","8b+","8c","8c+","9a","9a+","9b","9b+","9c"]},australian:{grades:["7","8","9/10","11","12","13","14/15","15/16","17","18","19","20","20/21","21","22","22/23","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39"]},south_african:{grades:["8","9","10/11","12","13","14","15","16","17/18","19","20","21","22","22/23","23/24","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41"]},uiaa:{grades:["iii-","iii","iii+","iv-","iv","iv+/v-","v-/v","v+/vi-","vi-/vi","vi/vi+","vii-","vii-/vii","vii/vii+","vii+","viii-","viii","viii/viii+","viii+","ix-","ix-/ix","ix/ix+","ix+","x-","x-/x","x/x+","x+","xi-","xi","xi+","xi+/xii-","xii-/xii","xii","xii+"],format:String.prototype.toUpperCase},british:{grades:["m 1","d 2","vd 3a","vd 3b/hvd 3b","hvd 3c/s 3c","ms 4a","s 4b/hs 4b","hs 4b/vs 4b","hvs 4c","hvs 5a","e1 5a","e1 5b","e2 5b","e2 5c","e3 5c","e3 6a","e4 6a","e4 6b","e5 6b","e5 6b/e6 6b","e6 6b","e6 6c","e7 6c","e7 7a","e8 7a","e8 7b","e9 7b","e10 7b","e10 7c","e11 7c","e11 8a","e11 8b","e11 8c"],format:function(){var e=this.split(" ")
return e[0].toUpperCase()+" "+e[1]}},hueco:{grades:["vb","vb","vb","vb","vb","vb","vb","vb","vb","vb","v0","v0+","v1","v2","v2","v3","v4","v4","v5","v5","v6","v7","v8","v8","v9","v10","v11","v12","v13","v14","v15","v16","v17"],format:String.prototype.toUpperCase},font:{grades:["1","1","1","1","1","1+","2","2+","3","3+","4","4+","5","5+","6a","6a+","6b","6b+","6c","6c+","7a","7a+","7b","7b+","7c","7c+","8a","8a+","8b","8b+","8c","8c+","9a"],format:String.prototype.toUpperCase}},this._universalGrades=this.getUniversalGrades()}function i(e,i){return i.format?i.format.call(e):e}var t=function(e,t){var r=this.getSystem(e)
if(e===this._inputSystemName)return i(this._inputGrade,r)
for(var a=t&&t.pairDelimeter?t.pairDelimeter:this._pairDelimeter,s=t&&t.rangeDelimeter?t.rangeDelimeter:this._rangeDelimeter,v=Object.create(null),n=this.getUniversalGrades(),b=[],o=0;o<n.length;o++)for(var c=r.grades[n[o]].split("/"),h=0;h<c.length;h++){var l=c[h],d=i(l,r)
d in v||(v[d]=!0,b.push(d))}return 1==b.length?b[0]:2==b.length?b.join(a):b.length>2?b[0]+s+b[b.length-1]:void 0}
return e.prototype.getSystem=function(e){var i=this._systems[e]
if(i)return i
throw new Error("Climbing System Not Recognized")},e.prototype.getUniversalGrades=function(){if(this._universalGrades)return this._universalGrades
for(var e=this._inputGrade.toLowerCase(),i=this.getSystem(this._inputSystemName).grades,t=[],r=0;r<i.length;r++)if(i[r].split("/").indexOf(e)>-1)t.push(r)
else if(t.length>0)break
if(0===t.length)throw new Error("Climbing Grade Not Recognized")
return t},e.prototype.format=function(e,i){return t.call(this,e,i)},e}()
"undefined"==typeof exports?this.ClimbingGrade=ClimbingGrade:module.exports=ClimbingGrade
<commit_msg>uglified<commit_after>var ClimbingGrade=function(){function i(i,e,t){this._inputGrade=i,this._inputSystemName=e,this._rangeDelimeter=t&&t.rangeDelimeter?t.rangeDelimeter:" to ",this._pairDelimeter=t&&t.pairDelimeter?t.pairDelimeter:"/",this._systems={yds:{grades:["5.1","5.2","5.3","5.4","5.5","5.6","5.7","5.8","5.9","5.10a","5.10b","5.10c","5.10d","5.11a","5.11b","5.11c","5.11d","5.12a","5.12b","5.12c","5.12d","5.13a","5.13b","5.13c","5.13d","5.14a","5.14b","5.14c","5.14d","5.15a","5.15b","5.15c","5.15d"]},french:{grades:["2","2+","3","3+","4","4+","5a","5b","5c","6a","6a+","6b","6b+","6c","6c/6c+","6c+","7a","7a+","7b","7b+","7c","7c+","8a","8a+","8b","8b+","8c","8c+","9a","9a+","9b","9b+","9c"]},australian:{grades:["7","8","9/10","11","12","13","14/15","15/16","17","18","19","20","20/21","21","22","22/23","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39"]},south_african:{grades:["8","9","10/11","12","13","14","15","16","17/18","19","20","21","22","22/23","23/24","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41"]},uiaa:{grades:["iii-","iii","iii+","iv-","iv","iv+/v-","v-/v","v+/vi-","vi-/vi","vi/vi+","vii-","vii-/vii","vii/vii+","vii+","viii-","viii","viii/viii+","viii+","ix-","ix-/ix","ix/ix+","ix+","x-","x-/x","x/x+","x+","xi-","xi","xi+","xi+/xii-","xii-/xii","xii","xii+"],format:String.prototype.toUpperCase},british:{grades:["m 1","d 2","vd 3a","vd 3b/hvd 3b","hvd 3c/s 3c","ms 4a","s 4b/hs 4b","hs 4b/vs 4b","hvs 4c","hvs 5a","e1 5a","e1 5b","e2 5b","e2 5c","e3 5c","e3 6a","e4 6a","e4 6b","e5 6b","e5 6b/e6 6b","e6 6b","e6 6c","e7 6c","e7 7a","e8 7a","e8 7b","e9 7b","e10 7b","e10 7c","e11 7c","e11 8a","e11 8b","e11 8c"],format:function(){var i=this.split(" ");return i[0].toUpperCase()+" "+i[1]}},hueco:{grades:["vb","vb","vb","vb","vb","vb","vb","vb","vb","vb","v0","v0+","v1","v2","v2","v3","v4","v4","v5","v5","v6","v7","v8","v8","v9","v10","v11","v12","v13","v14","v15","v16","v17"],format:String.prototype.toUpperCase},font:{grades:["1","1","1","1","1","1+","2","2+","3","3+","4","4+","5","5+","6a","6a+","6b","6b+","6c","6c+","7a","7a+","7b","7b+","7c","7c+","8a","8a+","8b","8b+","8c","8c+","9a"],format:String.prototype.toUpperCase},kurtyki:{grades:["ii","ii+","iii+","iv","iv+","v-","v","v+","vi","vi+","vi.1","vi.1+","vi.2","vi.2","vi.2+","vi.3","vi.3","vi.3+","vi.4","vi.4","vi.4+","vi.5","vi.5+","vi.5+/vi.6","vi.6","vi.6+","vi.7","vi.7+","vi.8","vi.8","vi.8","vi.8","vi.8","vi.8"],format:String.prototype.toUpperCase}},this._universalGrades=this.getUniversalGrades()}function e(i,e){return e.format?e.format.call(i):i}var t=function(i,t){var r=this.getSystem(i);if(i===this._inputSystemName)return e(this._inputGrade,r);for(var a=t&&t.pairDelimeter?t.pairDelimeter:this._pairDelimeter,v=t&&t.rangeDelimeter?t.rangeDelimeter:this._rangeDelimeter,s=Object.create(null),n=this.getUniversalGrades(),o=[],b=0;b<n.length;b++)for(var c=r.grades[n[b]].split("/"),h=0;h<c.length;h++){var l=c[h],d=e(l,r);d in s||(s[d]=!0,o.push(d))}return 1==o.length?o[0]:2==o.length?o.join(a):o.length>2?o[0]+v+o[o.length-1]:void 0};return i.prototype.getSystem=function(i){var e=this._systems[i];if(e)return e;throw Error("Climbing System Not Recognized")},i.prototype.getUniversalGrades=function(){if(this._universalGrades)return this._universalGrades;for(var i=this._inputGrade.toLowerCase(),e=this.getSystem(this._inputSystemName).grades,t=[],r=0;r<e.length;r++)if(e[r].split("/").indexOf(i)>-1)t.push(r);else if(t.length>0)break;if(0===t.length)throw Error("Climbing Grade Not Recognized");return t},i.prototype.format=function(i,e){return t.call(this,i,e)},i}();"undefined"==typeof exports?this.ClimbingGrade=ClimbingGrade:module.exports=ClimbingGrade;<|endoftext|>