<commit_before>// Generated by CoffeeScript 1.9.3
(function() {
  var $alchemy, $alchemyResult, $cost, $difficultydiff, $error, $export, $form, $kn, $main, $negative, $negativekn, $secondary, $values, addErrorProvider, addValueProvider, alchemyModifiers, calculateCost, calculateDifficulty, calculateNegativeDifficulty, clearDisplayValues, clearErrorMessage, costMultipliers, difficultyModifiers, errorProvider, exportData, getAlchemyValue, getFormData, getHtmlDifficultyModifier, getHtmlSpecialModifier, getNumber, hiddenModifiers, init, negativeDifficultyModifiers, renderAlchemyModifiers, renderAlchemyResult, renderAllSpecialModifiers, renderCost, renderDifficulty, renderEffectsDesc, renderHiddenModifier, renderHiddenModifiers, renderListData, renderModifiers, renderNegativeDifficulty, renderNegativeModifiers, renderSimpleValue, renderSpecialDifficultyModifierEffects, renderSpecialModifier, renderSuccess, specialDifficultyModifierEffects, specialDifficultyModifiers, t, testAlchemy, update;

  t = parser.t, addErrorProvider = parser.addErrorProvider, addValueProvider = parser.addValueProvider, difficultyModifiers = parser.difficultyModifiers, specialDifficultyModifiers = parser.specialDifficultyModifiers, negativeDifficultyModifiers = parser.negativeDifficultyModifiers, costMultipliers = parser.costMultipliers, calculateDifficulty = parser.calculateDifficulty, calculateCost = parser.calculateCost, calculateNegativeDifficulty = parser.calculateNegativeDifficulty, specialDifficultyModifierEffects = parser.specialDifficultyModifierEffects, alchemyModifiers = parser.alchemyModifiers, testAlchemy = parser.testAlchemy, hiddenModifiers = parser.hiddenModifiers;

  $main = $('#main_container_field');

  $secondary = $('#secondary_container_field');

  $kn = $('#kn_container_field');

  $negativekn = $('#negative_kn_container_field');

  $cost = $('#cost_container_field');

  $error = $('#error_container_field');

  $values = $('#values_container_field');

  $form = $('#form_data');

  $negative = $('#negative_value_container_filed');

  $difficultydiff = $('#difference_container_field');

  $alchemy = $('#alchemy_container_filed');

  $alchemyResult = $('#alchemy_result_container_field');

  $export = $('#export');

  errorProvider = function(errorMessage) {
    return $error.html("Hiba: " + errorMessage + "");
  };

  getNumber = function(label) {
    var values;
    $("#" + label).removeClass('hidden');
    values = $("[id*=" + label + "]").serializeArray();
    return _.reduce(values, (function(res, next) {
      return res * next.value.replace(/\D/g, '');
    }), 1);
  };

  addValueProvider('getNumber', getNumber);

  addErrorProvider(errorProvider);

  parser.init();

  clearDisplayValues = function() {
    return $values.children().addClass('hidden');
  };

  clearErrorMessage = function() {
    return $error.html('');
  };

  getHtmlDifficultyModifier = function(type, names) {
    var html;
    html = "
" + (t(type)) + ": ";
    html += "
<select class='form-control' id='id_" + type + "' name='" + type + "'>";
    html += _(names).keys().reduce((function(sum, key) {
      return sum + "\n<option value='" + key + "'>" + (t(key)) + "</option>";
    }), '');
    return html += "</select>

";
  };

  renderModifiers = function() {
    return renderListData($main, difficultyModifiers);
  };

  renderNegativeModifiers = function() {
    return renderListData($negative, negativeDifficultyModifiers);
  };

  renderAlchemyModifiers = function() {
    return renderListData($alchemy, alchemyModifiers);
  };

  renderListData = function($target, list) {
    var content;
    content = _(list).reduce((function(res, modifiers, name) {
      return res + "\n" + (getHtmlDifficultyModifier(name, modifiers));
    }), '');
    return $target.html(content);
  };

  getHtmlSpecialModifier = function(name, effect, selectedValue) {
    return " <input id='id_" + name + "_" + effect + "' type='radio' name='" + name + "' value='" + effect + "' " + (effect === selectedValue ? "checked='checked'" : "") + " /> " + (t(effect)) + " ";
  };

  renderSpecialModifier = function(name) {
    var effects, poisonType, selectedValue;
    poisonType = getFormData("tipus_" + name);
    effects = _(costMultipliers[poisonType].hatas).keys();
    selectedValue = getFormData(name);
    if (effects.indexOf(selectedValue) === -1) {
      selectedValue = effects.first();
    }
    return effects.reduce((function(res, effectName) {
      return res + "\n" + (getHtmlSpecialModifier(name, effectName, selectedValue));
    }), '');
  };

  renderAllSpecialModifiers = function() {
    var content;
    content = _(specialDifficultyModifiers).keys().reduce((function(res, type) {
      return res + "
" + (t(type)) + "
" + (renderSpecialModifier(type)) + "

";
    }), '');
    return $secondary.html(content);
  };

  renderSimpleValue = function(labelKey, value, type) {
    if (type == null) {
      type = 'info';
    }
    return "" + (t(labelKey)) + ": " + value + "";
  };

  renderCost = function() {
    var cost;
    cost = calculateCost(getFormData());
    $cost.html(renderSimpleValue('ar', cost));
    return cost;
  };

  renderDifficulty = function(item) {
    var difficulty, formData, knValue, negativeDifficulty, success, type;
    formData = getFormData();
    negativeDifficulty = calculateNegativeDifficulty(formData);
    difficulty = calculateDifficulty(formData, $(item).prop('name'), $('#id_meregkeveres').val());
    success = difficulty <= negativeDifficulty;
    if (success === true) {
      knValue = 'elegendő';
      type = 'success';
    } else {
      type = 'danger';
      knValue = 'sok';
    }
    knValue = knValue + " " + difficulty + " ≤ " + negativeDifficulty;
    knValue = difficulty ? knValue : 'Hiba!';
    $kn.html(renderSimpleValue('kn', knValue, type));
    return {
      success: success,
      difficulty: difficulty
    };
  };

  renderNegativeDifficulty = function() {
    var cost;
    cost = calculateNegativeDifficulty(getFormData());
    $negativekn.html(renderSimpleValue('negative', cost));
    return cost;
  };

  renderHiddenModifier = function(inputModifier, inputKey, modifierName) {
    var html, type;
    type = modifierName + "_" + inputKey;
    if (typeof inputModifier !== 'number') {
      return html = getHtmlDifficultyModifier(type, inputModifier);
    } else {
      html = "
" + (t(type)) + ": ";
      html += "
<input min='" + inputModifier + "' type='number' class='form-control' id='id_" + type + "' name='" + type + "' value='" + inputModifier + "' />";
      return html += "

";
    }
  };

  renderHiddenModifiers = function() {
    var content;
    content = _.reduce(hiddenModifiers, (function(res, next, key) {
      return res + ("
 <legend>" + (t(key)) + "</legend>\n") + (_.reduce(next.inputs, (function(res, next, innerKey) {
        return res + renderHiddenModifier(next, innerKey, key);
      }), '')) + "
";
    }), '');
    return $values.html(content);
  };

  renderEffectsDesc = function() {
    return _.each(['eros', 'gyenge'], function(level) {
      return $("#desc_" + level).html(renderSpecialDifficultyModifierEffects($("[name='" + level + "']:checked").val()));
    });
  };

  renderSpecialDifficultyModifierEffects = function(specialModifier) {
    var add, content, effects, labels;
    labels = specialDifficultyModifierEffects.labels;
    effects = specialDifficultyModifierEffects[specialModifier];
    if (effects == null) {
      return '';
    }
    add = window.self !== window.top ? 'background-color: rgba(100, 100, 100,0.1)' : '';
    content = "

";
    content += _.reduce(labels, (function(res, next) {
      return res + ("" + next + "	");
    }), '');
    content += '

';
    content += _.reduce(effects, (function(res, next) {
      return res + ("" + (next === 0 ? '-' : next) + "	");
    }), '');
    return content += "

";
  };

  renderAlchemyResult = function(difficulty) {
    var alchemyValue, diff, type;
    alchemyValue = getAlchemyValue(difficulty);
    if (alchemyValue.test === true) {
      diff = 'megfelelő';
      type = 'success';
    } else {
      diff = 'elégtelen';
      type = 'danger';
    }
    diff = diff + " " + alchemyValue.neededAlchemyLevel + " ≤ " + alchemyValue.availableAlchemyLevel;
    $alchemyResult.html(renderSimpleValue('alkímia felszerelés', diff, type));
    return alchemyValue.test;
  };

  renderSuccess = function(difficultySuccess, alchemyValue) {
    var diff, type;
    if ((difficultySuccess === true) && (alchemyValue === true)) {
      diff = 'igen';
      type = 'success';
    } else {
      diff = 'nem';
      type = 'danger';
    }
    $difficultydiff.html(renderSimpleValue('kikeverhető', diff, type));
    return diff === 'igen';
  };

  getAlchemyValue = function(difficulty) {
    var alchemyLevel, supplyType;
    alchemyLevel = $('#id_alkimia').val();
    supplyType = $('#id_felszereles').val();
    return testAlchemy(supplyType, difficulty, alchemyLevel);
  };

  getFormData = function(attr) {
    var data, ref;
    data = $form.serializeArray();
    if (!attr) {
      return data;
    }
    return (ref = _(data).find({
      name: attr
    })) != null ? ref.value : void 0;
  };

  exportData = function(event) {
    var alchemy, cost, data, difficulty, formAllData, formData, name, negativeDifficulty, results, success, values;
    formAllData = getFormData();
    values = _.map($values.find('.hidden_input').not('.hidden').map(function() {
      return this.id;
    }), function(id) {
      return [t(id), hiddenModifiers[id].calculate($("#" + id + " :input").serializeArray())];
    });
    formData = _.reject(formAllData, function(input) {
      var match;
      return match = _.find(hiddenModifiers, function(modifier, modifierKey) {
        return new RegExp(modifierKey + ".*").test(input.name);
      });
    });
    difficulty = calculateDifficulty(formData, null, $('#id_meregkeveres').val());
    negativeDifficulty = calculateNegativeDifficulty(formData);
    alchemy = getAlchemyValue(difficulty);
    success = difficulty <= negativeDifficulty && alchemy.test;
    cost = calculateCost(formData);
    if (success === false) {
      errorProvider('A mérget nem lehet kikeverni, ezért az nem exportálható!');
      return;
    }
    name = prompt('Írj be egy fájlnevet a méregnek!', "mereg_" + (new Date() * 1));
    if (!name) {
      return;
    }
    results = [['Név', name], ['Kikeverési nehézség', difficulty], ['Karakter KN értéke', negativeDifficulty], ['Alkímia szint', alchemy.availableAlchemyLevel], ['Szükséges alkímia szint', alchemy.neededAlchemyLevel], ['A méreg ára', cost + " ezüst"]];
    data = _.map(formData, function(row) {
      return [t(row.name), t(row.value)];
    });
    data = _.concat(results, data, values);
    return saveData(name, 'mereg', data);
  };

  update = function(event) {
    var alchemy, difficulty;
    renderEffectsDesc();
    clearDisplayValues();
    clearErrorMessage();
    renderCost();
    difficulty = renderDifficulty(event.target);
    alchemy = renderAlchemyResult(difficulty.difficulty);
    return renderSuccess(difficulty.success, alchemy);
  };

  init = function() {
    var alchemy, difficulty;
    if (window.self !== window.top) {
      $('body').css('background-color', 'transparent');
      $('#main-body').attr('class', 'container-fluid');
    }
    renderModifiers();
    renderNegativeModifiers();
    renderAlchemyModifiers();
    renderAllSpecialModifiers();
    renderEffectsDesc();
    renderHiddenModifiers();
    difficulty = renderDifficulty();
    alchemy = renderAlchemyResult(difficulty.difficulty);
    renderSuccess(difficulty.success, alchemy);
    renderCost();
    clearErrorMessage();
    clearDisplayValues();
    $export.click(exportData);
    $('form').on('change', '#id_tipus_fo', function(event) {
      return $('#id_tipus_eros, #id_tipus_gyenge').val($(event.target).val());
    });
    $('form').on('change', 'select[name^="tipus"]', function() {
      return renderAllSpecialModifiers(event.target.id.slice(9));
    });
    $('form').on('change', 'select, input[type="radio"]', update);
    $('form').on('input', 'input', update);
    return setTimeout((function() {
      return $('body').show();
    }), 0);
  };

  init();

}).call(this);
<commit_msg> final 2.2<commit_after>// Generated by CoffeeScript 1.9.3
(function() {
  var $alchemy, $alchemyResult, $cost, $difficultydiff, $error, $export, $form, $kn, $main, $negative, $negativekn, $secondary, $values, addErrorProvider, addValueProvider, alchemyModifiers, calculateCost, calculateDifficulty, calculateNegativeDifficulty, clearDisplayValues, clearErrorMessage, costMultipliers, difficultyModifiers, errorProvider, exportData, getAlchemyValue, getFormData, getHtmlDifficultyModifier, getHtmlSpecialModifier, getNumber, hiddenModifiers, init, negativeDifficultyModifiers, renderAlchemyModifiers, renderAlchemyResult, renderAllSpecialModifiers, renderCost, renderDifficulty, renderEffectsDesc, renderHiddenModifier, renderHiddenModifiers, renderListData, renderModifiers, renderNegativeDifficulty, renderNegativeModifiers, renderSimpleValue, renderSpecialDifficultyModifierEffects, renderSpecialModifier, renderSuccess, specialDifficultyModifierEffects, specialDifficultyModifiers, t, testAlchemy, update;

  t = parser.t, addErrorProvider = parser.addErrorProvider, addValueProvider = parser.addValueProvider, difficultyModifiers = parser.difficultyModifiers, specialDifficultyModifiers = parser.specialDifficultyModifiers, negativeDifficultyModifiers = parser.negativeDifficultyModifiers, costMultipliers = parser.costMultipliers, calculateDifficulty = parser.calculateDifficulty, calculateCost = parser.calculateCost, calculateNegativeDifficulty = parser.calculateNegativeDifficulty, specialDifficultyModifierEffects = parser.specialDifficultyModifierEffects, alchemyModifiers = parser.alchemyModifiers, testAlchemy = parser.testAlchemy, hiddenModifiers = parser.hiddenModifiers;

  $main = $('#main_container_field');

  $secondary = $('#secondary_container_field');

  $kn = $('#kn_container_field');

  $negativekn = $('#negative_kn_container_field');

  $cost = $('#cost_container_field');

  $error = $('#error_container_field');

  $values = $('#values_container_field');

  $form = $('#form_data');

  $negative = $('#negative_value_container_filed');

  $difficultydiff = $('#difference_container_field');

  $alchemy = $('#alchemy_container_filed');

  $alchemyResult = $('#alchemy_result_container_field');

  $export = $('#export');

  errorProvider = function(errorMessage) {
    return $error.html("Hiba: " + errorMessage + "");
  };

  getNumber = function(label) {
    var values;
    $("#" + label).removeClass('hidden');
    values = $("[id*=" + label + "]").serializeArray();
    return _.reduce(values, (function(res, next) {
      return res * next.value.replace(/\D/g, '');
    }), 1);
  };

  addValueProvider('getNumber', getNumber);

  addErrorProvider(errorProvider);

  parser.init();

  clearDisplayValues = function() {
    return $values.children().addClass('hidden');
  };

  clearErrorMessage = function() {
    return $error.html('');
  };

  getHtmlDifficultyModifier = function(type, names) {
    var html;
    html = "
" + (t(type)) + ": ";
    html += "
<select class='form-control' id='id_" + type + "' name='" + type + "'>";
    html += _(names).keys().reduce((function(sum, key) {
      return sum + "\n<option value='" + key + "'>" + (t(key)) + "</option>";
    }), '');
    return html += "</select>

";
  };

  renderModifiers = function() {
    return renderListData($main, difficultyModifiers);
  };

  renderNegativeModifiers = function() {
    return renderListData($negative, negativeDifficultyModifiers);
  };

  renderAlchemyModifiers = function() {
    return renderListData($alchemy, alchemyModifiers);
  };

  renderListData = function($target, list) {
    var content;
    content = _(list).reduce((function(res, modifiers, name) {
      return res + "\n" + (getHtmlDifficultyModifier(name, modifiers));
    }), '');
    return $target.html(content);
  };

  getHtmlSpecialModifier = function(name, effect, selectedValue) {
    return " <input id='id_" + name + "_" + effect + "' type='radio' name='" + name + "' value='" + effect + "' " + (effect === selectedValue ? "checked='checked'" : "") + " /> " + (t(effect)) + " ";
  };

  renderSpecialModifier = function(name) {
    var effects, poisonType, selectedValue;
    poisonType = getFormData("tipus_" + name);
    effects = _(costMultipliers[poisonType].hatas).keys();
    selectedValue = getFormData(name);
    if (effects.indexOf(selectedValue) === -1) {
      selectedValue = effects.first();
    }
    return effects.reduce((function(res, effectName) {
      return res + "\n" + (getHtmlSpecialModifier(name, effectName, selectedValue));
    }), '');
  };

  renderAllSpecialModifiers = function() {
    var content;
    content = _(specialDifficultyModifiers).keys().reduce((function(res, type) {
      return res + "
" + (t(type)) + "
" + (renderSpecialModifier(type)) + "

";
    }), '');
    return $secondary.html(content);
  };

  renderSimpleValue = function(labelKey, value, type) {
    if (type == null) {
      type = 'info';
    }
    return "" + (t(labelKey)) + ": " + value + "";
  };

  renderCost = function() {
    var cost;
    cost = calculateCost(getFormData());
    $cost.html(renderSimpleValue('ar', cost));
    return cost;
  };

  renderDifficulty = function(item) {
    var difficulty, formData, knValue, negativeDifficulty, success, type;
    formData = getFormData();
    negativeDifficulty = calculateNegativeDifficulty(formData);
    difficulty = calculateDifficulty(formData, $(item).prop('name'), $('#id_meregkeveres').val());
    success = difficulty <= negativeDifficulty;
    if (success === true) {
      knValue = 'elegendő';
      type = 'success';
    } else {
      type = 'danger';
      knValue = 'sok';
    }
    knValue = knValue + " " + difficulty + " ≤ " + negativeDifficulty;
    knValue = difficulty ? knValue : 'Hiba!';
    $kn.html(renderSimpleValue('kn', knValue, type));
    return {
      success: success,
      difficulty: difficulty
    };
  };

  renderNegativeDifficulty = function() {
    var cost;
    cost = calculateNegativeDifficulty(getFormData());
    $negativekn.html(renderSimpleValue('negative', cost));
    return cost;
  };

  renderHiddenModifier = function(inputModifier, inputKey, modifierName) {
    var html, type;
    type = modifierName + "_" + inputKey;
    if (typeof inputModifier !== 'number') {
      return html = getHtmlDifficultyModifier(type, inputModifier);
    } else {
      html = "
" + (t(type)) + ": ";
      html += "
<input min='" + inputModifier + "' type='number' class='form-control' id='id_" + type + "' name='" + type + "' value='" + inputModifier + "' />";
      return html += "

";
    }
  };

  renderHiddenModifiers = function() {
    var content;
    content = _.reduce(hiddenModifiers, (function(res, next, key) {
      return res + ("
 <legend>" + (t(key)) + "</legend>\n") + (_.reduce(next.inputs, (function(res, next, innerKey) {
        return res + renderHiddenModifier(next, innerKey, key);
      }), '')) + "
";
    }), '');
    return $values.html(content);
  };

  renderEffectsDesc = function() {
    return _.each(['eros', 'gyenge'], function(level) {
      return $("#desc_" + level).html(renderSpecialDifficultyModifierEffects($("[name='" + level + "']:checked").val()));
    });
  };

  renderSpecialDifficultyModifierEffects = function(specialModifier) {
    var add, content, effects, labels;
    labels = specialDifficultyModifierEffects.labels;
    effects = specialDifficultyModifierEffects[specialModifier];
    if (effects == null) {
      return '';
    }
    add = window.self !== window.top ? 'background-color: rgba(100, 100, 100,0.1)' : '';
    content = "

";
    content += _.reduce(labels, (function(res, next) {
      return res + ("" + next + "	");
    }), '');
    content += '

';
    content += _.reduce(effects, (function(res, next) {
      return res + ("" + (next === 0 ? '-' : next) + "	");
    }), '');
    return content += "

";
  };

  renderAlchemyResult = function(difficulty) {
    var alchemyValue, diff, type;
    alchemyValue = getAlchemyValue(difficulty);
    if (alchemyValue.test === true) {
      diff = 'megfelelő';
      type = 'success';
    } else {
      diff = 'elégtelen';
      type = 'danger';
    }
    diff = diff + " " + alchemyValue.neededAlchemyLevel + " ≤ " + alchemyValue.availableAlchemyLevel;
    $alchemyResult.html(renderSimpleValue('alkímia felszerelés', diff, type));
    return alchemyValue.test;
  };

  renderSuccess = function(difficultySuccess, alchemyValue) {
    var diff, type;
    if ((difficultySuccess === true) && (alchemyValue === true)) {
      diff = 'igen';
      type = 'success';
    } else {
      diff = 'nem';
      type = 'danger';
    }
    $difficultydiff.html(renderSimpleValue('kikeverhető', diff, type));
    return diff === 'igen';
  };

  getAlchemyValue = function(difficulty) {
    var alchemyLevel, supplyType;
    alchemyLevel = $('#id_alkimia').val();
    supplyType = $('#id_felszereles').val();
    return testAlchemy(supplyType, difficulty, alchemyLevel);
  };

  getFormData = function(attr) {
    var data, ref;
    data = $form.serializeArray();
    if (!attr) {
      return data;
    }
    return (ref = _(data).find({
      name: attr
    })) != null ? ref.value : void 0;
  };

  exportData = function(event) {
    var alchemy, cost, data, difficulty, formAllData, formData, name, negativeDifficulty, results, success, values;
    formAllData = getFormData();
    values = _.map($values.find('.hidden_input').not('.hidden').map(function() {
      return this.id;
    }), function(id) {
      return [t(id), hiddenModifiers[id].calculate($("#" + id + " :input").serializeArray())];
    });
    formData = _.reject(formAllData, function(input) {
      var match;
      return match = _.find(hiddenModifiers, function(modifier, modifierKey) {
        return new RegExp(modifierKey + ".*").test(input.name);
      });
    });
    difficulty = calculateDifficulty(formData, null, $('#id_meregkeveres').val());
    negativeDifficulty = calculateNegativeDifficulty(formData);
    alchemy = getAlchemyValue(difficulty);
    success = difficulty <= negativeDifficulty && alchemy.test;
    cost = calculateCost(formData);
    if (success === false) {
      errorProvider('A mérget nem lehet kikeverni, ezért az nem exportálható!');
      return;
    }
    name = prompt('Írj be egy fájlnevet a méregnek!', "mereg_" + (new Date() * 1));
    if (!name) {
      return;
    }
    results = [['Név', name], ['Kikeverési nehézség', difficulty], ['Karakter KN értéke', negativeDifficulty], ['Alkímia szint', alchemy.availableAlchemyLevel], ['Szükséges alkímia szint', alchemy.neededAlchemyLevel], ['A méreg ára', cost + " ezüst"]];
    data = _.map(formData, function(row) {
      return [t(row.name), t(row.value)];
    });
    data = _.concat(results, data, values);
    return saveData(name, 'mereg', data);
  };

  update = function(event) {
    var alchemy, difficulty;
    renderEffectsDesc();
    clearDisplayValues();
    clearErrorMessage();
    renderCost();
    difficulty = renderDifficulty(event.target);
    alchemy = renderAlchemyResult(difficulty.difficulty);
    return renderSuccess(difficulty.success, alchemy);
  };

  init = function() {
    var alchemy, difficulty;
    if (window.self !== window.top) {
      $('body').css('background-color', 'transparent');
      $('#main-body').attr('class', 'container-fluid');
    }
    renderModifiers();
    renderNegativeModifiers();
    renderAlchemyModifiers();
    renderAllSpecialModifiers();
    renderEffectsDesc();
    renderHiddenModifiers();
    difficulty = renderDifficulty();
    alchemy = renderAlchemyResult(difficulty.difficulty);
    renderSuccess(difficulty.success, alchemy);
    renderCost();
    clearErrorMessage();
    clearDisplayValues();
    $export.click(exportData);
    $('form').on('change', '#id_tipus_fo', function(event) {
      return $('#id_tipus_eros, #id_tipus_gyenge').val($(event.target).val());
    });
    $('form').on('change', 'select[name^="tipus"]', function() {
      return renderAllSpecialModifiers();
    });
    $('form').on('change', 'select, input[type="radio"]', update);
    $('form').on('input', 'input', update);
    return setTimeout((function() {
      return $('body').show();
    }), 0);
  };

  init();

}).call(this);
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var path = require('path');
var async = require('async');
var crypto = require('crypto');
var defaultDefinitions = [{
  "require": "blank-container",
  "type": "blank-container"
}, {
  "require": "docker-container",
  "type": "docker"
}, {
  "require": "process-container",
  "type": "process"
}, {
  "require": "aws-elb-container",
  "type": "aws-elb"
}, {
  "require": "aws-sg-container",
  "type": "aws-sg"
}, {
  "require": "aws-ami-container",
  "type": "aws-ami"
}, {
  "require": "aws-autoscaling-container",
  "type": "aws-autoscaling"
}];

module.exports = function(loadConfig, logger, sr) {
  // this is setted up to leak memory over time
  // we are allocating a new container object for each system
  // that is deployed. However adding system is almost a
  // once-per-installation operation
  var containers = {};
  var digests = {};
  var services = {};

  function getContainers(config, system, cb) {

    delete config.logger;

    var shasum = crypto.createHash('sha1');
    shasum.update(JSON.stringify(config));
    var digest = shasum.digest('hex');
    var toDelete;

    // clean up old containers for this system
    // as the config changed
    if (digests[system.id] !== digest && containers[system.id]) {
      toDelete = containers[system.id];
      delete containers[system.id];

      return async.eachSeries(Object.keys(toDelete), function(key, cb) {
        if (toDelete[key].release) {
          return toDelete[key].release(cb);
        }
        cb();
      }, complete);
    }

    return complete();

    function complete(err) {
      if (err) {
        return cb(err);
      }

      // we need a default
      config.containers = config.containers || [];

      if (!containers[system.id]) {
        containers[system.id] = {};
      }

      digests[system.id] = digest;
      cb(null, containers[system.id]);
    }
  }

  function getDefinition(config, type) {
    var def = _.find(config.containers, function(def) { return def.type === type });

    if (!def) {
      def = _.find(defaultDefinitions, function(def) { return def.type === type });
    }

    if (def) {
      def.specific = def.specific || {};
    }

    return def;
  }

  function applyDefaults(config, def) {
    [ 'root',
      'systemsRoot',
      'buildRoot',
      'targetRoot',
      'mode',
      'region',
      'sshKeyPath',
      'identityFile',
      'accessKeyId',
      'secretAccessKey',
      'defaultSubnetId',
      'defaultVpcId',
      'defaultImageId',
      'tagAppend',
      'defaultInstanceType',
      'defaultKeyName' ].forEach(function(key) {
        def.specific[key] = config[key] || config.kernel[key] || def.specific[key];
      });
  }

  function buildHandler(config, type) {
    var def = getDefinition(config, type);
    var childLogger = logger.child({ module: def.type });

    if (!def) {
      throw new Error('no such definition ' + type);
    }

    applyDefaults(config, def);
    def.specific.startedService = services[type];

    childLogger.debug('requiring');

    return require(def.require)(def.specific, childLogger);
  }

  function getHandler(system, type, cb) {
    loadConfig(system, function(err, config) {
      if (err) { return cb(err); }

      getContainers(config, system, function(err, containers) {
        if (err) { return cb(err); }

        var definition;
        var childLogger;

        if (!containers[type]) {
          containers[type] = buildHandler(config, type);
        }

        cb(null, containers[type]);
      });
    });
  }

  function startService(config, api, sr, type, cb) {
    var instance = buildHandler(config, type);
    var root = path.resolve(path.join(config.kernel.systemsRoot, '..'));
    if (instance.service) {
      logger.debug({ module: type }, 'starting');
      if (instance.service.length == 2) {
        instance.service(root, finish);
      } else if (instance.service.length == 3) {
        instance.service(root, api, finish);
      } else if (instance.service.length == 4) {
        instance.service(root, api, sr, finish);
      } else if (instance.service.length == 5) {
        instance.service(root, api, sr, loadConfig, finish);
      }
    } else {
      cb();
    }

    function finish(err, server) {
      if (server) {
        server.type = type;
      }
      cb(err, server);
    }
  }

  function listTypes(config) {
    return _.chain(config.containers || [])
            .map(function(def) { return def.type })
            .concat(_.map(defaultDefinitions, function(def) { return def.type }))
            .uniq()
            .value();
  }

  function startAllServices(config, api, sr, cb) {
    var types = listTypes(config);
    async.map(types, startService.bind(null, config, api, sr), function(err, servers) {
      services = _.chain(servers).compact().indexBy('type').value();
      cb(err, servers);
    });
  }

  function toRelease() {
    var result = [];
    Object.keys(containers).forEach(function(systemKey) {
      Object.keys(containers[systemKey]).forEach(function(containerKey) {
        if (containers[systemKey][containerKey].release) {
          result.push(containers[systemKey][containerKey]);
        }
      });
    });
    return result;
  }

  function toClose() {
    return _.map(Object.keys(services), function(key) { return services[key]; });
  }

  function buildStopFunction(items, thingToDo) {

    return function(cb) {

      function onNextItem(item, callback) {
        item[thingToDo](function(err) {
          callback(err);
        });
      }

      function done(err) {
        cb(err);
      }

      async.eachSeries(items, onNextItem, done);
    };
  }

  function stopAllServices(cb) {
    logger.info('Stopping all services');
    var releaseAll = buildStopFunction(toRelease(), 'release');
    var closeAll = buildStopFunction(toClose(), 'close');

    releaseAll(function(err) {
      closeAll(function(err) {
        cb(err);
      });
    });
  }

  return {
    getHandler: getHandler,
    listTypes: listTypes,
    startAllServices: startAllServices,
    stopAllServices: stopAllServices
  };
};
<commit_msg>handle process container service<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var path = require('path');
var async = require('async');
var crypto = require('crypto');
var defaultDefinitions = [{
  "require": "blank-container",
  "type": "blank-container"
}, {
  "require": "docker-container",
  "type": "docker"
}, {
  "require": "process-container",
  "type": "process"
}, {
  "require": "aws-elb-container",
  "type": "aws-elb"
}, {
  "require": "aws-sg-container",
  "type": "aws-sg"
}, {
  "require": "aws-ami-container",
  "type": "aws-ami"
}, {
  "require": "aws-autoscaling-container",
  "type": "aws-autoscaling"
}];

module.exports = function(loadConfig, logger, sr) {
  // this is setted up to leak memory over time
  // we are allocating a new container object for each system
  // that is deployed. However adding system is almost a
  // once-per-installation operation
  var containers = {};
  var digests = {};
  var services = {};

  function getContainers(config, system, cb) {

    delete config.logger;

    var shasum = crypto.createHash('sha1');
    shasum.update(JSON.stringify(config));
    var digest = shasum.digest('hex');
    var toDelete;

    // clean up old containers for this system
    // as the config changed
    if (digests[system.id] !== digest && containers[system.id]) {
      toDelete = containers[system.id];
      delete containers[system.id];

      return async.eachSeries(Object.keys(toDelete), function(key, cb) {
        if (toDelete[key].release) {
          return toDelete[key].release(cb);
        }
        cb();
      }, complete);
    }

    return complete();

    function complete(err) {
      if (err) {
        return cb(err);
      }

      // we need a default
      config.containers = config.containers || [];

      if (!containers[system.id]) {
        containers[system.id] = {};
      }

      digests[system.id] = digest;
      cb(null, containers[system.id]);
    }
  }

  function getDefinition(config, type) {
    var def = _.find(config.containers, function(def) { return def.type === type });

    if (!def) {
      def = _.find(defaultDefinitions, function(def) { return def.type === type });
    }

    if (def) {
      def.specific = def.specific || {};
    }

    return def;
  }

  function applyDefaults(config, def) {
    [ 'root',
      'systemsRoot',
      'buildRoot',
      'targetRoot',
      'mode',
      'region',
      'sshKeyPath',
      'identityFile',
      'accessKeyId',
      'secretAccessKey',
      'defaultSubnetId',
      'defaultVpcId',
      'defaultImageId',
      'tagAppend',
      'defaultInstanceType',
      'defaultKeyName' ].forEach(function(key) {
        def.specific[key] = config[key] || config.kernel[key] || def.specific[key];
      });
  }

  function buildHandler(config, type) {
    var def = getDefinition(config, type);
    var childLogger = logger.child({ module: def.type });

    if (!def) {
      throw new Error('no such definition ' + type);
    }

    applyDefaults(config, def);
    def.specific.startedService = services[type];

    childLogger.debug('requiring');

    return require(def.require)(def.specific, childLogger);
  }

  function getHandler(system, type, cb) {
    loadConfig(system, function(err, config) {
      if (err) { return cb(err); }

      getContainers(config, system, function(err, containers) {
        if (err) { return cb(err); }

        var definition;
        var childLogger;

        if (!containers[type]) {
          containers[type] = buildHandler(config, type);
        }

        cb(null, containers[type]);
      });
    });
  }

  function startService(config, api, sr, type, cb) {
    var instance = buildHandler(config, type);
    var root = path.resolve(path.join(config.kernel.systemsRoot, '..'));
    if (instance.service) {
      logger.debug({ module: type }, 'starting');
      if (instance.service.length == 1) {
        instance.service(finish);
      } else if (instance.service.length == 2) {
        instance.service(root, finish);
      } else if (instance.service.length == 3) {
        instance.service(root, api, finish);
      } else if (instance.service.length == 4) {
        instance.service(root, api, sr, finish);
      } else if (instance.service.length == 5) {
        instance.service(root, api, sr, loadConfig, finish);
      }
    } else {
      cb();
    }

    function finish(err, server) {
      if (server) {
        server.type = type;
      }
      cb(err, server);
    }
  }

  function listTypes(config) {
    return _.chain(config.containers || [])
            .map(function(def) { return def.type })
            .concat(_.map(defaultDefinitions, function(def) { return def.type }))
            .uniq()
            .value();
  }

  function startAllServices(config, api, sr, cb) {
    var types = listTypes(config);
    async.map(types, startService.bind(null, config, api, sr), function(err, servers) {
      services = _.chain(servers).compact().indexBy('type').value();
      cb(err, servers);
    });
  }

  function toRelease() {
    var result = [];
    Object.keys(containers).forEach(function(systemKey) {
      Object.keys(containers[systemKey]).forEach(function(containerKey) {
        if (containers[systemKey][containerKey].release) {
          result.push(containers[systemKey][containerKey]);
        }
      });
    });
    return result;
  }

  function toClose() {
    return _.map(Object.keys(services), function(key) { return services[key]; });
  }

  function buildStopFunction(items, thingToDo) {

    return function(cb) {

      function onNextItem(item, callback) {
        item[thingToDo](function(err) {
          callback(err);
        });
      }

      function done(err) {
        cb(err);
      }

      async.eachSeries(items, onNextItem, done);
    };
  }

  function stopAllServices(cb) {
    logger.info('Stopping all services');
    var releaseAll = buildStopFunction(toRelease(), 'release');
    var closeAll = buildStopFunction(toClose(), 'close');

    releaseAll(function(err) {
      closeAll(function(err) {
        cb(err);
      });
    });
  }

  return {
    getHandler: getHandler,
    listTypes: listTypes,
    startAllServices: startAllServices,
    stopAllServices: stopAllServices
  };
};
<|endoftext|>


<commit_before>
(function (window, document, version, callback) {

    // only run this script once per page.
    if (window.embedScriptIncluded) return;

    window.embedScriptIncluded = true;

    // get the script location.
    var s = document.getElementById('embedWellcomePlayer');
    var scriptUri = (/.*src="(.*)"/).exec(s.outerHTML)[1];
    var absScriptUri = s.src;

    var j, d;
    var loaded = false;

    // only load jQuery if not already included in page.
    if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, scriptUri, absScriptUri, loaded)) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "//ajax.googleapis.com/ajax/libs/jquery/" + version + "/jquery.min.js";
        script.onload = script.onreadystatechange = function () {
            if (!loaded && (!(d = this.readyState) || d === "loaded" || d === "complete")) {
                callback((j = window.jQuery).noConflict(1), scriptUri, absScriptUri, loaded = true);
                j(script).remove();
            }
        };
        document.getElementsByTagName("head")[0].appendChild(script);
    }
})(window, document, "1.10.1", function ($, scriptUri, absScriptUri, jqueryLoaded) {

    $.support.cors = true;

    function createCookie(name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }
        else var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    // get the part preceding 'js/embed.js'
    var baseUri = (/(.*)js\/embed.js/).exec(scriptUri)[1];
    appUri = baseUri + 'app.html';
    easyXDMUri = baseUri + 'js/easyXDM.min.js';
    json2Uri = baseUri + 'js/json2.min.js';

    var a = document.createElement('a');
    a.href = absScriptUri;
    var domain = a.hostname;

    $.when($.getScript(easyXDMUri),
           $.getScript(json2Uri)).done(function () {
               var apps = $('.wellcomePlayer');

               var isHomeDomain = document.domain === domain;
               var isOnlyInstance = apps.length === 1;

               for (var i = 0; i < apps.length; i++) {
                   app(apps[i], isHomeDomain, isOnlyInstance);
               }
           });

    function app(element, isHomeDomain, isOnlyInstance) {
        var socket, $app, $appFrame, dataUri, assetSequenceIndex, assetIndex, dataBaseUri, zoom, config, isFullScreen, height, top, left, lastScroll, reload;

        $app = $(element);

        // empty the container of any 'no javascript' messages.
        $app.empty();

        // get initial params from the container's 'data-' attributes.
        dataBaseUri = $app.attr('data-baseuri');
        if (dataBaseUri) dataBaseUri = encodeURIComponent(dataBaseUri);
        dataUri = $app.attr('data-uri');
        dataUri = encodeURIComponent(dataUri);
        assetSequenceIndex = $app.attr('data-assetsequenceindex');
        assetIndex = $app.attr('data-assetindex');
        zoom = $app.attr('data-zoom');
        config = $app.attr('data-config');

        isFullScreen = false;
        height = $app.height();
        var position = $app.position();
        top = position.top;
        left = position.left;

        $(window).resize(function () {
            resize();
        });

        window.onorientationchange = function () {
            resize();
        };

        createSocket();

        function resize() {
            if (!$appFrame) return;

            if (isFullScreen) {
                $appFrame.width($(this).width());
                $appFrame.height($(this).height());
            } else {
                $appFrame.width($app.width());
                $appFrame.height($app.height());
            }
        }

        function redirect(uri) {
            // store current location in cookie.
            createCookie('wlredirect', window.location.href);
            window.location.replace(uri);
        }

        function refresh() {
            window.location.reload();
        }

        function triggerSocket(eventName, eventObject) {
            socket.postMessage(JSON.stringify({ eventName: eventName, eventObject: eventObject }));
        }

        function toggleFullScreen(fs) {
            isFullScreen = fs;

            if (isFullScreen) {

                // store current scroll position.
                lastScroll = $(document).scrollTop();

                $("html").css("overflow", "hidden");
                window.scrollTo(0, 0);

                $appFrame.css({
                    'position': 'absolute',
                    'z-index': 9999,
                    'height': $(window).height(),
                    'width': $(window).width(),
                    'top': ($app[0].offsetParent.offsetTop * -1) || 0,
                    'left': ($app[0].offsetParent.offsetLeft * -1) || 0
                });
            } else {
                $("html").css("overflow", "auto");

                $appFrame.css({
                    'position': 'static',
                    'z-index': 'auto',
                    'height': height,
                    'width': '100%',
                    'top': top,
                    'left': left
                });

                // return to last scroll position.
                window.scrollTo(0, lastScroll);
            }

            resize();
        }

        function viewAssetSequence(index) {

            $appFrame.prop('src', '');
            $app.empty();

            assetSequenceIndex = index;
            reload = true;

            createSocket();
        }

        function createSocket() {

            var uri = appUri +
                "?hd=" + isHomeDomain +
                "&oi=" + isOnlyInstance +
                "&du=" + dataUri +
                "&esu=" + absScriptUri +
                "&d=" + domain;

            if (assetSequenceIndex) uri += "&asi=" + assetSequenceIndex;
            if (assetIndex) uri += "&ai=" + assetIndex;
            if (dataBaseUri) uri += "&dbu=" + dataBaseUri;
            if (zoom) uri += "&z=" + zoom;
            if (reload) uri += "&rl=true";
            if (config) uri += "&c=" + config;

            socket = new easyXDM.Socket({
                remote: uri,
                container: $app.get(0),
                props: { style: { width: "100%", height: $app.height() + "px" }, scrolling: "no" },
                onReady: function () {
                    $appFrame = $app.find('iframe');
                },
                onMessage: function (message, origin) {
                    message = $.parseJSON(message);

                    switch (message.eventName) {
                        case "onToggleFullScreen":
                            toggleFullScreen(message.eventObject);
                            break;
                        case "onAssetSequenceIndexChanged":
                            viewAssetSequence(message.eventObject);
                            break;
                        case "onRedirect":
                            redirect(message.eventObject);
                            break;
                        case "onRefresh":
                            refresh();
                            break;
                        case "onTrackEvent":
                            if ("undefined" !== typeof (trackEvent)) {
                                trackEvent(message.eventObject.category, message.eventObject.action, message.eventObject.label, message.eventObject.value);
                            }
                            break;
                        case "onTrackVariable":
                            if ("undefined" !== typeof (trackVariable)) {
                                trackVariable(message.eventObject.slot, message.eventObject.name, message.eventObject.value, message.eventObject.scope);
                            }
                            break;
                        default:
                            try{
                                jQuery(document).trigger(message.eventName, [message.eventObject]);
                            } catch(e) {
                                // do nothing
                            }
                            break;
                    }
                }
            });
        }
    }
});<commit_msg>support lack of id on script tag<commit_after>
(function (window, document, version, callback) {

    // only run this script once per page.
    if (window.embedScriptIncluded) return;

    window.embedScriptIncluded = true;

    // get the script location.
    var s = document.getElementById('embedWellcomePlayer');

    if (!s){
        var scripts = document.getElementsByTagName('script');
        s = scripts[scripts.length - 1];
    }

    var scriptUri = (/.*src="(.*)"/).exec(s.outerHTML)[1];
    var absScriptUri = s.src;

    var j, d;
    var loaded = false;

    // only load jQuery if not already included in page.
    if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, scriptUri, absScriptUri, loaded)) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "//ajax.googleapis.com/ajax/libs/jquery/" + version + "/jquery.min.js";
        script.onload = script.onreadystatechange = function () {
            if (!loaded && (!(d = this.readyState) || d === "loaded" || d === "complete")) {
                callback((j = window.jQuery).noConflict(1), scriptUri, absScriptUri, loaded = true);
                j(script).remove();
            }
        };
        document.getElementsByTagName("head")[0].appendChild(script);
    }
})(window, document, "1.10.1", function ($, scriptUri, absScriptUri, jqueryLoaded) {

    $.support.cors = true;

    function createCookie(name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }
        else var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    // get the part preceding 'js/embed.js'
    var baseUri = (/(.*)js\/embed.js/).exec(scriptUri)[1];
    appUri = baseUri + 'app.html';
    easyXDMUri = baseUri + 'js/easyXDM.min.js';
    json2Uri = baseUri + 'js/json2.min.js';

    var a = document.createElement('a');
    a.href = absScriptUri;
    var domain = a.hostname;

    $.when($.getScript(easyXDMUri),
           $.getScript(json2Uri)).done(function () {
               var apps = $('.wellcomePlayer');

               var isHomeDomain = document.domain === domain;
               var isOnlyInstance = apps.length === 1;

               for (var i = 0; i < apps.length; i++) {
                   app(apps[i], isHomeDomain, isOnlyInstance);
               }
           });

    function app(element, isHomeDomain, isOnlyInstance) {
        var socket, $app, $appFrame, dataUri, assetSequenceIndex, assetIndex, dataBaseUri, zoom, config, isFullScreen, height, top, left, lastScroll, reload;

        $app = $(element);

        // empty the container of any 'no javascript' messages.
        $app.empty();

        // get initial params from the container's 'data-' attributes.
        dataBaseUri = $app.attr('data-baseuri');
        if (dataBaseUri) dataBaseUri = encodeURIComponent(dataBaseUri);
        dataUri = $app.attr('data-uri');
        dataUri = encodeURIComponent(dataUri);
        assetSequenceIndex = $app.attr('data-assetsequenceindex');
        assetIndex = $app.attr('data-assetindex');
        zoom = $app.attr('data-zoom');
        config = $app.attr('data-config');

        isFullScreen = false;
        height = $app.height();
        var position = $app.position();
        top = position.top;
        left = position.left;

        $(window).resize(function () {
            resize();
        });

        window.onorientationchange = function () {
            resize();
        };

        createSocket();

        function resize() {
            if (!$appFrame) return;

            if (isFullScreen) {
                $appFrame.width($(this).width());
                $appFrame.height($(this).height());
            } else {
                $appFrame.width($app.width());
                $appFrame.height($app.height());
            }
        }

        function redirect(uri) {
            // store current location in cookie.
            createCookie('wlredirect', window.location.href);
            window.location.replace(uri);
        }

        function refresh() {
            window.location.reload();
        }

        function triggerSocket(eventName, eventObject) {
            socket.postMessage(JSON.stringify({ eventName: eventName, eventObject: eventObject }));
        }

        function toggleFullScreen(fs) {
            isFullScreen = fs;

            if (isFullScreen) {

                // store current scroll position.
                lastScroll = $(document).scrollTop();

                $("html").css("overflow", "hidden");
                window.scrollTo(0, 0);

                $appFrame.css({
                    'position': 'absolute',
                    'z-index': 9999,
                    'height': $(window).height(),
                    'width': $(window).width(),
                    'top': ($app[0].offsetParent.offsetTop * -1) || 0,
                    'left': ($app[0].offsetParent.offsetLeft * -1) || 0
                });
            } else {
                $("html").css("overflow", "auto");

                $appFrame.css({
                    'position': 'static',
                    'z-index': 'auto',
                    'height': height,
                    'width': '100%',
                    'top': top,
                    'left': left
                });

                // return to last scroll position.
                window.scrollTo(0, lastScroll);
            }

            resize();
        }

        function viewAssetSequence(index) {

            $appFrame.prop('src', '');
            $app.empty();

            assetSequenceIndex = index;
            reload = true;

            createSocket();
        }

        function createSocket() {

            var uri = appUri +
                "?hd=" + isHomeDomain +
                "&oi=" + isOnlyInstance +
                "&du=" + dataUri +
                "&esu=" + absScriptUri +
                "&d=" + domain;

            if (assetSequenceIndex) uri += "&asi=" + assetSequenceIndex;
            if (assetIndex) uri += "&ai=" + assetIndex;
            if (dataBaseUri) uri += "&dbu=" + dataBaseUri;
            if (zoom) uri += "&z=" + zoom;
            if (reload) uri += "&rl=true";
            if (config) uri += "&c=" + config;

            socket = new easyXDM.Socket({
                remote: uri,
                container: $app.get(0),
                props: { style: { width: "100%", height: $app.height() + "px" }, scrolling: "no" },
                onReady: function () {
                    $appFrame = $app.find('iframe');
                },
                onMessage: function (message, origin) {
                    message = $.parseJSON(message);

                    switch (message.eventName) {
                        case "onToggleFullScreen":
                            toggleFullScreen(message.eventObject);
                            break;
                        case "onAssetSequenceIndexChanged":
                            viewAssetSequence(message.eventObject);
                            break;
                        case "onRedirect":
                            redirect(message.eventObject);
                            break;
                        case "onRefresh":
                            refresh();
                            break;
                        case "onTrackEvent":
                            if ("undefined" !== typeof (trackEvent)) {
                                trackEvent(message.eventObject.category, message.eventObject.action, message.eventObject.label, message.eventObject.value);
                            }
                            break;
                        case "onTrackVariable":
                            if ("undefined" !== typeof (trackVariable)) {
                                trackVariable(message.eventObject.slot, message.eventObject.name, message.eventObject.value, message.eventObject.scope);
                            }
                            break;
                        default:
                            try{
                                jQuery(document).trigger(message.eventName, [message.eventObject]);
                            } catch(e) {
                                // do nothing
                            }
                            break;
                    }
                }
            });
        }
    }
});<|endoftext|>


<commit_before>'use strict';

const App = require('./app').App;

const app = new App();
app.run();

process.on('uncaughtException', err => {
  console.log(`caught exception: ${err}`);
});

process.on('unhandledRejection', (reason, p) => {
  console.log(`unhandled rejection at promise: ${p} reason: ${reason}`);
});
<commit_msg>Limit http request to avoid ECONRESET error.<commit_after>'use strict';

var http = require('http');
var https = require('https');
const App = require('./app').App;

http.globalAgent.maxSockets = 2;
https.globalAgent.maxSockets = 2;

const app = new App();
app.run();
<|endoftext|>


<commit_before>import isNil from 'ramda/src/isNil';
import isEmpty from 'ramda/src/isEmpty';

const validate = val  => {
  if (isNil(val)) {
    return true;
  }

  if (isEmpty(val)){
    return false;
  }

  const regexp = /^\d*$/g;

  return regexp.test(String(val));
};

const message = '<%= propertyName %> must be a digit.';

export default {validate, message};
<commit_msg>Fix false positive on value isEmpty<commit_after>import isNil from 'ramda/src/isNil';
import isEmpty from 'ramda/src/isEmpty';

const regexp = /^\d*$/;

const validate = val  => {
  if (isNil(val)) {
    return true;
  }

  const stringVal = String(val);

  if (isEmpty(stringVal)){
    return false;
  }

  return regexp.test(stringVal);
};

const message = '<%= propertyName %> must be a digit.';

export default {validate, message};
<|endoftext|>


<commit_before>var $ = require("jquery");
global.jQuery = require("jquery");
window.jQuery = $;
(function($) {
  $.fn.fader = function(options) {
    // default settings
    var settings = $.extend(
      {
        fadeSpeed: 500,
        duration: 2000,
        citeDelay: 1200,
        citeFadeSpeed: 750
      },
      options
    );
    /**
     * Fades out element `toFade`, fading in `toFade+1`
     * If `toFade` is the last element, then the first element will be
     * faded in.
     *
     * @param {Integer} toFade which element to fade out
     * @param {Array} testimonial array of jQuery elements
     */
    function fade(toFade, testimonial, cite) {
      // fade OUT element to opacity 0
      testimonial[toFade].animate(
        {
          opacity: 0
        },
        settings.fadeSpeed
      );
      cite[toFade].animate(
        {
          opacity: 0
        },
        settings.fadeSpeed
      );
      var toShow = toFade === testimonial.length - 1 ? 0 : toFade + 1; // fade IN element to opacity 1
      testimonial[toShow].animate(
        {
          opacity: 1
        },
        settings.fadeSpeed
      );
      cite[toShow]
        .stop(true, true)
        .delay(settings.citeDelay)
        .animate(
          {
            opacity: 1
          },
          settings.citeFadeSpeed
        ); // set duration of element
      setTimeout(function() {
        fade(toShow, testimonial, cite);
      }, settings.duration);
    } // find li, add to text array and hide them
    var testimonial = [];
    $(this)
      .find("li blockquote")
      .each(function() {
        testimonial.push($(this));
        $(this).css({
          opacity: 0
        });
      }); // find li, add to text array and hide them
    var cite = [];
    $(this)
      .find("li cite")
      .each(function() {
        cite.push($(this));
        $(this).css({
          opacity: 0
        });
      }); // fade in first item in array
    testimonial[0].animate(
      {
        opacity: 1
      },
      settings.fadeSpeed / 2
    ); // run function
    setTimeout(function() {
      fade(0, testimonial, cite);
    }, settings.duration);
    cite[0]
      .stop(true, true)
      .delay(settings.citeDelay / 2)
      .animate(
        {
          opacity: 1
        },
        settings.fadeSpeed / 2
      );
  };
})(jQuery);
<commit_msg>Updating code readability<commit_after>// imports
var $ = require("jquery");
global.jQuery = require("jquery");
window.jQuery = $;

// function
(function($) {
  $.fn.fader = function(options) {
    // default settings
    var settings = $.extend(
      {
        fadeSpeed: 500,
        duration: 2000,
        citeDelay: 1200,
        citeFadeSpeed: 750
      },
      options
    );

    /**
     * Fades out element `toFade`, fading in `toFade+1`
     * If `toFade` is the last element, then the first element will be
     * faded in.
     *
     * @param {Integer} toFade which element to fade out
     * @param {Array} testimonial array of jQuery elements
     */
    function fade(toFade, testimonial, cite) {
      // fade OUT element to opacity 0
      testimonial[toFade].animate(
        {
          opacity: 0
        },
        settings.fadeSpeed
      );
      cite[toFade].animate(
        {
          opacity: 0
        },
        settings.fadeSpeed
      );
      var toShow = toFade === testimonial.length - 1 ? 0 : toFade + 1; // fade IN element to opacity 1
      testimonial[toShow].animate(
        {
          opacity: 1
        },
        settings.fadeSpeed
      );
      cite[toShow]
        .stop(true, true)
        .delay(settings.citeDelay)
        .animate(
          {
            opacity: 1
          },
          settings.citeFadeSpeed
        ); // set duration of element
      setTimeout(function() {
        fade(toShow, testimonial, cite);
      }, settings.duration);
    }

    // find li, add to text array and hide them
    var testimonial = [];
    $(this)
      .find("li blockquote")
      .each(function() {
        testimonial.push($(this));
        $(this).css({
          opacity: 0
        });
      });

    // find li, add to text array and hide them
    var cite = [];
    $(this)
      .find("li cite")
      .each(function() {
        cite.push($(this));
        $(this).css({
          opacity: 0
        });
      }); // fade in first item in array
    testimonial[0].animate(
      {
        opacity: 1
      },
      settings.fadeSpeed / 2
    );

    // run function
    setTimeout(function() {
      fade(0, testimonial, cite);
    }, settings.duration);
    cite[0]
      .stop(true, true)
      .delay(settings.citeDelay / 2)
      .animate(
        {
          opacity: 1
        },
        settings.fadeSpeed / 2
      );
  };
})(jQuery);
<|endoftext|>


<commit_before>import path from 'path';
import postcss from 'postcss';
import 'string.prototype.includes';

const defaultResolutions = [
  '(min--moz-device-pixel-ratio: 1.5)',
  '(-o-min-device-pixel-ratio: 3/2)',
  '(-webkit-min-device-pixel-ratio: 1.5)',
  '(min-device-pixel-ratio: 1.5)',
  '(min-resolution: 144dpi)',
  '(min-resolution: 1.5dppx)'
];

export default postcss.plugin('postcss-at2x', at2x);

function at2x({ identifier = '@2x' } = {}) {
  return function(root) {
    // Create an empty rule so that all the new rules can be appended to this
    // and then append it at the end. Adding them to original `root` means
    // PostCSS then loops over the new rules in the `eachRule`
    // and creates extra loops and sadness.
    const ruleContainer = postcss.root();

    // Create the standard retina media at rule here so that all rules
    // can be appended into one rather than duplicating the params each time
    const retinaMediaAtRule = postcss.atRule({
      name: 'media',
      params: defaultResolutions.join(', ')
    });

    root.eachRule((rule) => {
      const mediaParent = rule.parent;

      // Check for any `background-size` declarations and keep a reference to it
      // These need to be added again to prevent it being overridden by usage of
      // the `background` shorthand
      let backgroundSize;
      rule.eachDecl('background-size', decl => backgroundSize = decl);

      rule.eachDecl(/^background/, (decl) => {
        // Exit if it's a normal background declaration
        if (!backgroundWithHiResURL(decl.value)) {
          return;
        }

        // Strip out `at-2x` from image url
        decl.value = decl.value.replace(/\s+(at-2x)\s*(;|$)/, '$2');

        // Construct a duplicate rule but with the image urls
        // replaced with retina versions
        const retinaRule = postcss.rule({ selector: decl.parent.selector });
        retinaRule.append(postcss.decl({
          prop: decl.prop,
          value: createRetinaUrl(decl.value, identifier)
        }));

        // Add back any `background-size` value
        if (backgroundSize) {
          retinaRule.append(postcss.decl(backgroundSize));
        }

        // If retina image is within a media query then ensure each size gets
        // the retina resolutions. Append these one at the time because each set
        // of atRule params will be different
        //
        // Otherwise just append them to the media rule declared previously
        if (mediaParent.name === 'media') {
          const params = combineMediaQuery(mediaParent.params.split(/,\s*/), defaultResolutions);
          const scopedRetinaMediaAtRule = postcss.atRule({ name: 'media', params });

          scopedRetinaMediaAtRule.append(retinaRule);
          ruleContainer.append(scopedRetinaMediaAtRule);
        } else {
          retinaMediaAtRule.append(retinaRule);
        }
      });
    });

    // There is a chance ruleContainer could be empty, so check for it
    if (retinaMediaAtRule.nodes) {
      ruleContainer.append(retinaMediaAtRule);
    }

    // Add all the new rules to the bottom of the stylesheet
    root.append(ruleContainer);
  };
}

/**
 * Add all the resolutions to each media query to scope them
 */
function combineMediaQuery(queries, resolutions) {
  return queries.reduce((finalQuery, query) => {
    resolutions.forEach(resolution => finalQuery.push(`${query} and ${resolution}`));
    return finalQuery;
  }, []).join(', ');
}

const urlPathRegex = /url\((.*?)\)/gm;

function createRetinaUrl(bgValue, identifier) {
  // Loop over all occurances of `url()` and match the path
  let match;
  while ((match = urlPathRegex.exec(bgValue)) !== null) {
    const [, url] = match;
    const extension = path.extname(url);

    if (extension === '.svg') {
      break;
    }

    // File name without extension
    const filename = path.basename(path.basename(url), extension);
    // Replace with retina filename
    bgValue = bgValue.replace(new RegExp(`(${filename})(${extension})`, 'gm'), `$1${identifier}$2`);
  }

  return bgValue;
}

function backgroundWithHiResURL(bgValue) {
  return bgValue.includes('url(') && bgValue.includes('at-2x');
}
<commit_msg>Improve regex to use negated character class<commit_after>import path from 'path';
import postcss from 'postcss';
import 'string.prototype.includes';

const defaultResolutions = [
  '(min--moz-device-pixel-ratio: 1.5)',
  '(-o-min-device-pixel-ratio: 3/2)',
  '(-webkit-min-device-pixel-ratio: 1.5)',
  '(min-device-pixel-ratio: 1.5)',
  '(min-resolution: 144dpi)',
  '(min-resolution: 1.5dppx)'
];

export default postcss.plugin('postcss-at2x', at2x);

function at2x({ identifier = '@2x' } = {}) {
  return function(root) {
    // Create an empty rule so that all the new rules can be appended to this
    // and then append it at the end. Adding them to original `root` means
    // PostCSS then loops over the new rules in the `eachRule`
    // and creates extra loops and sadness.
    const ruleContainer = postcss.root();

    // Create the standard retina media at rule here so that all rules
    // can be appended into one rather than duplicating the params each time
    const retinaMediaAtRule = postcss.atRule({
      name: 'media',
      params: defaultResolutions.join(', ')
    });

    root.eachRule((rule) => {
      const mediaParent = rule.parent;

      // Check for any `background-size` declarations and keep a reference to it
      // These need to be added again to prevent it being overridden by usage of
      // the `background` shorthand
      let backgroundSize;
      rule.eachDecl('background-size', decl => backgroundSize = decl);

      rule.eachDecl(/^background/, (decl) => {
        // Exit if it's a normal background declaration
        if (!backgroundWithHiResURL(decl.value)) {
          return;
        }

        // Strip out `at-2x` from image url
        decl.value = decl.value.replace(/\s+(at-2x)\s*(;|$)/, '$2');

        // Construct a duplicate rule but with the image urls
        // replaced with retina versions
        const retinaRule = postcss.rule({ selector: decl.parent.selector });
        retinaRule.append(postcss.decl({
          prop: decl.prop,
          value: createRetinaUrl(decl.value, identifier)
        }));

        // Add back any `background-size` value
        if (backgroundSize) {
          retinaRule.append(postcss.decl(backgroundSize));
        }

        // If retina image is within a media query then ensure each size gets
        // the retina resolutions. Append these one at the time because each set
        // of atRule params will be different
        //
        // Otherwise just append them to the media rule declared previously
        if (mediaParent.name === 'media') {
          const params = combineMediaQuery(mediaParent.params.split(/,\s*/), defaultResolutions);
          const scopedRetinaMediaAtRule = postcss.atRule({ name: 'media', params });

          scopedRetinaMediaAtRule.append(retinaRule);
          ruleContainer.append(scopedRetinaMediaAtRule);
        } else {
          retinaMediaAtRule.append(retinaRule);
        }
      });
    });

    // There is a chance ruleContainer could be empty, so check for it
    if (retinaMediaAtRule.nodes) {
      ruleContainer.append(retinaMediaAtRule);
    }

    // Add all the new rules to the bottom of the stylesheet
    root.append(ruleContainer);
  };
}

/**
 * Add all the resolutions to each media query to scope them
 */
function combineMediaQuery(queries, resolutions) {
  return queries.reduce((finalQuery, query) => {
    resolutions.forEach(resolution => finalQuery.push(`${query} and ${resolution}`));
    return finalQuery;
  }, []).join(', ');
}

const urlPathRegex = /url\(([^\r\n]+)\)/gm;

function createRetinaUrl(bgValue, identifier) {
  // Loop over all occurances of `url()` and match the path
  let match;
  while ((match = urlPathRegex.exec(bgValue)) !== null) {
    const [, url] = match;
    const extension = path.extname(url);

    if (extension === '.svg') {
      break;
    }

    // File name without extension
    const filename = path.basename(path.basename(url), extension);
    // Replace with retina filename
    bgValue = bgValue.replace(new RegExp(`(${filename})(${extension})`, 'gm'), `$1${identifier}$2`);
  }

  return bgValue;
}

function backgroundWithHiResURL(bgValue) {
  return bgValue.includes('url(') && bgValue.includes('at-2x');
}
<|endoftext|>