<commit_before>'use strict';

var fs = require('fs');
var tutils = require('./tutils');
var tbox = require('tbox');
var userInfo = require('./userinfo');

function UserDB(filePath) {
  var path = filePath;
  var userDB = {
    'users':[]
  };

  this.setDBPath = function(p) {
    path = p;
  };

  this.getDBPath = function() {
    return path;
  };

  this.createUser = function(id, nick) {
    var newUser = {};
    newUser.id = id;
    newUser.nick = nick;
    newUser.admin = false;
    newUser.avatar = '';
    newUser.status = 'pending'; // pending, active, banned
    return newUser;
  };

  this.createAdmin = function(id, nick) {
    var admin = {};
    admin = this.createUser(id, nick);
    admin.admin = true;
    admin.status = 'active';
    return admin;
  };

  this.addUser = function(user) { // user is object like { id: 'TEST'}
    if(!this.checkForUser(user.id)) {
      userDB.users.push(user);
      this.saveDB();
      return true;
    } else {
      return false;
    }
  };

  this.getUser = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return userDB.users[i];
      }
    }
  };

  this.getAllUsers = function() {
    return userDB.users;
  };

  this.removeUser = function(userId) {
    var index = this.getUserIndex(userId);
    if (index !== (-1)) {
      userDB.users.splice(index, 1);
      this.saveDB();
      return true;
    }
    return false;
  };

  this.checkForUser = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return true;
      }
    }
    return false;
  };

  this.getUserIndex = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return i;
      }
    }
    return (-1);
  };

  this.createDefaultDB = function() {
    this.addUser(this.createAdmin('ADMIN', 'admin'));
    return userDB;
  };

  this.loadDB = function() {
    try {
      userDB = JSON.parse(fs.readFileSync(path));
      console.log('[DEBUG] DB loading [OK]');
    } catch(e) {
      console.log(e);
      // TODO понадобится обрабатывать ситуационные ошибки и в
      // зависимости от конкретной ошибки выполнять соответствующие действаия
      // в том числе если вываливается исключение на синтаксис JSON файла
      console.log('[DEBUG] create default DB');
      userDB = this.createDefaultDB();
      this.tryToWrite('default DB');//TODO шозанах?????
    }
  };

  this.saveDB = function() {
    //TODO необходимо сделать асинхронную запсь
    this.tryToWrite('userDB');
  };

  this.tryToWrite = function(str) {
    try {
      fs.writeFileSync(path, JSON.stringify(userDB));
      console.log('[DEBUG] %s successfully saved!', str);
    } catch (err) {
      console.log(err);
      console.log('[DEBUG] unable to save %s with path: %j', str, path);
    }
  };
}

exports.UserDB = UserDB;
<commit_msg>Update<commit_after>'use strict';

var fs = require('fs');
var tutils = require('./tutils');
var tbox = require('tbox');
var userInfo = require('./userinfo');

function UserDB(filePath) {
  var path = filePath;
  var userDB = {
    'users':[]
  };

  this.setDBPath = function(p) {
    path = p;
  };

  this.getDBPath = function() {
    return path;
  };

  this.createUser = function(id, nick) {
    var newUser = {};
    newUser.id = id;
    newUser.nick = nick;
    newUser.admin = false;
    newUser.avatar = '';
    newUser.status = 'pending'; // pending, active, banned
    return newUser;
  };

  this.createAdmin = function(id, nick) {
    var admin = {};
    admin = this.createUser(id, nick);
    admin.admin = true;
    admin.status = 'active';
    return admin;
  };

  this.addUser = function(user) { // user is object like { id: 'TEST'}
    if(!this.checkForUser(user.id)) {
      userDB.users.push(user);
      return true;
    } else {
      return false;
    }
  };

  this.getUser = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return userDB.users[i];
      }
    }
  };

  this.getAllUsers = function() {
    return userDB.users;
  };

  this.removeUser = function(userId) {
    var index = this.getUserIndex(userId);
    if (index !== (-1)) {
      userDB.users.splice(index, 1);
      return true;
    }
    return false;
  };

  this.checkForUser = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return true;
      }
    }
    return false;
  };

  this.getUserIndex = function(userId) {
    for(var i = 0; i < userDB.users.length; i++) {
      if(userDB.users[i].id === userId) {
        return i;
      }
    }
    return (-1);
  };

  this.createDefaultDB = function() {
    this.addUser(this.createAdmin('ADMIN', 'admin'));
    return userDB;
  };

  this.loadDB = function() {
    try {
      userDB = JSON.parse(fs.readFileSync(path));
      console.log('[USERDB] DB loading [OK]');
    } catch(e) {
      console.log('[USERDB] ' + e.message);
      console.log('[USERDB] create default DB');
      userDB = this.createDefaultDB();
      this.tryToWrite('default DB');
    }
  };

  this.saveDB = function() {
    //TODO необходимо сделать асинхронную запсь
    this.tryToWrite('userDB');
  };

  this.tryToWrite = function(str) {
    try {
      fs.writeFileSync(path, JSON.stringify(userDB));
      console.log('[USERDB] %s successfully saved!', str);
    } catch (err) {
      console.log(err);
      console.log('[USERDB] unable to save %s with path: %j', str, path);
    }
  };
}

exports.UserDB = UserDB;
<|endoftext|>


<commit_before>/* jshint jquery:true, browser:true */
/* global KeyCodes */

$(document).ready(function () {
  'use strict';

  var catsnap = window.catsnap,
      sendImage,
      receiveImageData,
      showError,
      tagLink,
      appendAddPane,
      saveAttributes,
      saveAlbum,
      availableRow,
      checkForImage;

  sendImage = function(event) {
    var $this = $(this),
        formData = new FormData(this),
        $article = $this.parent('article');

    event.preventDefault();
    $this.find('input').addClass('disabled').attr('disabled', true);
    formData.append('album_id', $('select[name="album"]').val());

    $article.find('div.alert').remove();

    $.ajax($this.attr('action') + '.json', {
      type: $this.attr('method'),
      data: formData,
      contentType: false,
      processData: false,
      success: function(data) {
        var $newAddPane = $article.clone(true);
        $article.remove();

        $.each(data, function(i, datum) {
          var $editPane = $('
'),
              $targetRow = availableRow();

          $targetRow.append($editPane);
          receiveImageData.call($editPane, datum);
        });

        appendAddPane($newAddPane);
      },
      error: function(data) {
        $article.find('form').show();
        $article.find('img').remove();
        $this.find('input').removeClass('disabled').attr('disabled', false);
        showError.call($article, data);
      }
    });
  };

  receiveImageData = function(data) {
    var delay = 2000, //milliseconds
        $titleInput = $('<input type="text" name="title" placeholder="Title" class="form-control">'),
        $form,
        $ul;

    this.append($(''));
    this.data('image-id', data.image_id);
    this.data('url', data.url);

    $titleInput.on('keydown', function(event) {
      if (event.which === KeyCodes.ENTER) {
        event.preventDefault();
        $form.submit();
      }
    });

    window.setTimeout(checkForImage.bind(this, delay), delay);

    $form = $('<form method="post" action="#">');
    $form.append($titleInput);

    $ul = $('

');
    $ul.children('li').append(tagLink.call(this));
    $form.append($ul);

    $form.append($('<textarea placeholder="Description" ' +
             'class="form-control" name="description">'));
    $form.append($('<input type="submit" value="Save" ' +
             'class="btn btn-default edit" name="save">'));
    $form.submit(saveAttributes);
    $form.find('input').blur(function() {
      $(this).parent('form').submit();
    });
    this.append($form);
  };

  saveAttributes = function(event) {
    var $form = $(this),
        $saveButton = $form.find('input[type="submit"]'),
        $titleInput = $form.find('input[name="title"]'),
        $descriptionInput = $form.find('textarea[name="description"]'),
        $article = $form.parent('article');

    event.preventDefault();

    $saveButton.addClass('disabled');
    $.ajax(window.catsnap.editingUrl($article), {
      type: "PATCH",
      data: {
        title: $titleInput.val(),
        description: $descriptionInput.val(),
      },
      success: function() {
        $saveButton.removeClass('disabled');
      },
      error: function(data, status, errorThrown) {
        showError.call($article, errorThrown);
        $saveButton.removeClass('disabled');
      }
    });
  };

  appendAddPane = function($article) {
    var $targetRow = availableRow();

    $targetRow.append($article);
    $article.find('input').val(null);
    $article.find('input').removeClass('disabled').attr('disabled', false);
    $article.find('input[type="submit"]').val('Go');
    $article.find('label').text('Select');
    $article.show();
  };

  availableRow = function() {
    var $lastRow = $('.row').last();
    if ($lastRow.find('article').length >= 3) {
      $lastRow.parent().append($('
'));
    }
    return $('.row').last();
  };

  tagLink = function() {
    var $container = this,
        $addButton = $('<button class="btn btn-xs btn-default add-tag"></button>'),
        $a = $('Add tag');

    function startEditing(event) {
      var abortEditing,
          submitTag,
          $thisLi = $(event.target).parent(),
          $tagInput,
          $form;
      event.preventDefault();
      $thisLi.find('*').hide();

      $form = $('<form><input type="submit" class="enter-to-submit"></form>');
      $tagInput = $('<input type="text" class="edit form-control" name="tag" autocapitalize="none">');
      $form.prepend($tagInput);

      abortEditing = catsnap.generateAbortEditing($tagInput, $a.add($addButton), $tagInput);

      submitTag = window.catsnap.generateSubmitTag(
          $form, $container, abortEditing, showError.bind($container), function() {
        var $nextLi = $('
'),
            $removeButton = $('<button class="btn btn-xs btn-default remove-tag">'),
            $xSign = $(''),
            $tag = $(''),
            tagName = $tagInput.val().trim(),
            removeTag,
            newTagLink;

        $thisLi.find('*').remove();

        removeTag = catsnap.generateRemoveTag($container, $thisLi.remove);

        $tag.text(tagName);
        $removeButton.append($xSign);
        $thisLi.append([$removeButton, ' ', $tag]);
        $removeButton.click(removeTag);
        $tag.click(removeTag);

        newTagLink = tagLink.call($container);
        $nextLi.append(newTagLink);
        $container.find('ul').append($nextLi);
      });

      $tagInput.blur(submitTag);
      $form.submit(submitTag);
      catsnap.tagKeyListeners($form, abortEditing, function() {
        $thisLi.siblings().find('a').click();
      });

      $thisLi.append($form);
      $a.parent().append($thisLi);
      $form.find('input').focus();
    }

    $addButton.click(startEditing);
    $a.click(startEditing);

    return [$addButton, ' ', $a];
  };

  showError = function(data) {
    var message = data.responseJSON.error;
    this.find('div.alert').remove();
    this.prepend($('
' + message + '
'));
  };

  checkForImage = function(previousTimeout) {
    var $container = this,
        url = this.data('url'),
        newTimeout = previousTimeout * 1.4,
        $a = $(''),
        $img = $('');

    $img.error(function() {
      $img.off('error');
      $img.error(function() {
        window.setTimeout(checkForImage.bind($container, newTimeout), newTimeout);
      });
      $img.attr('src', url);
    });
    $img.load(function() {
      $container.find('img').remove();
      $a.append($img);
      $container.prepend($a);
    });
    $img.attr('src', url + '_thumbnail');
  };

  saveAlbum = function(event) {
    var $form = $(this),
        $modalHeader = $('#new-album').find('.modal-header'),
        $albumInput = $form.find('input[type="text"]'),
        albumName = $albumInput.val();

    event.preventDefault();

    $.ajax($form.attr('action') + '.json', {
      type: "POST",
      data: {name: albumName},
      success: function(data) {
        var $albumDropdown = $('#album'),
            $modal = $('#new-album'),
            $option;

        $option = $('<option>');
        $option.text(albumName);
        $option.val(data.album_id);
        $albumDropdown.append($option);
        $albumDropdown.val(data.album_id);

        $modalHeader.find('div.alert').remove();
        $albumInput.val('');
        $modal.modal('hide');
      },
      error: showError.bind($modalHeader),
    });
  };

  $('.image-control form').submit(sendImage);
  $('#new-album form').submit(saveAlbum);
  $('input[type="file"]').on('change', function() {
    var numFiles = $(this).prop('files').length,
        displayText = $(this).val();

    if (numFiles > 1) {
      displayText = displayText + ', ' + (numFiles - 1) + ' more';
    }
    $(this).siblings('label').text(displayText);
  });
});
<commit_msg>Remove nested forms in the edit-after-add pane [#45]<commit_after>/* jshint jquery:true, browser:true */
/* global KeyCodes */

$(document).ready(function () {
  'use strict';

  var catsnap = window.catsnap,
      sendImage,
      receiveImageData,
      showError,
      tagLink,
      appendAddPane,
      saveAttributes,
      saveAlbum,
      availableRow,
      checkForImage;

  sendImage = function(event) {
    var $this = $(this),
        formData = new FormData(this),
        $article = $this.parent('article');

    event.preventDefault();
    $this.find('input').addClass('disabled').attr('disabled', true);
    formData.append('album_id', $('select[name="album"]').val());

    $article.find('div.alert').remove();

    $.ajax($this.attr('action') + '.json', {
      type: $this.attr('method'),
      data: formData,
      contentType: false,
      processData: false,
      success: function(data) {
        var $newAddPane = $article.clone(true);
        $article.remove();

        $.each(data, function(i, datum) {
          var $editPane = $('
'),
              $targetRow = availableRow();

          $targetRow.append($editPane);
          receiveImageData.call($editPane, datum);
        });

        appendAddPane($newAddPane);
      },
      error: function(data) {
        $article.find('form').show();
        $article.find('img').remove();
        $this.find('input').removeClass('disabled').attr('disabled', false);
        showError.call($article, data);
      }
    });
  };

  receiveImageData = function(data) {
    var delay = 2000, //milliseconds
        $titleInput,
        $titleForm,
        $descriptionArea,
        $descriptionForm,
        $ul;

    this.append($(''));
    this.data('image-id', data.image_id);
    this.data('url', data.url);

    window.setTimeout(checkForImage.bind(this, delay), delay);

    $titleInput = $('<input type="text" placeholder="Title" ' +
                    'name="title" class="form-control">');
    $descriptionArea = $('<textarea placeholder="Description" ' +
                         'class="form-control" name="description">');

    $($titleInput).add($descriptionArea).blur(function() {
      $(this).parent('form').submit();
    });

    $titleForm = $('<form method="post" action="#">');
    $titleForm.submit(saveAttributes);
    $titleForm.append($titleInput);
    this.append($titleForm);

    $ul = $('

');
    $ul.children('li').append(tagLink.call(this));
    this.append($ul);

    $descriptionForm = $('<form method="post" action="#">');
    $descriptionForm.append($descriptionArea);
    $descriptionForm.append($('<input type="submit" value="Save" ' +
             'class="btn btn-default edit" name="save">'));
    $descriptionForm.submit(saveAttributes);

    this.append($descriptionForm);
  };

  saveAttributes = function(event) {
    var $form = $(this),
        $article = $form.parent('article'),
        $saveButton = $article.find('input[type="submit"]'),
        $titleInput = $article.find('input[name="title"]'),
        $descriptionInput = $article.find('textarea[name="description"]');

    event.preventDefault();

    $saveButton.addClass('disabled');
    $.ajax(window.catsnap.editingUrl($article), {
      type: "PATCH",
      data: {
        title: $titleInput.val(),
        description: $descriptionInput.val(),
      },
      success: function() {
        $saveButton.removeClass('disabled');
      },
      error: function(data, status, errorThrown) {
        showError.call($article, errorThrown);
        $saveButton.removeClass('disabled');
      }
    });
  };

  appendAddPane = function($article) {
    var $targetRow = availableRow();

    $targetRow.append($article);
    $article.find('input').val(null);
    $article.find('input').removeClass('disabled').attr('disabled', false);
    $article.find('input[type="submit"]').val('Go');
    $article.find('label').text('Select');
    $article.show();
  };

  availableRow = function() {
    var $lastRow = $('.row').last();
    if ($lastRow.find('article').length >= 3) {
      $lastRow.parent().append($('
'));
    }
    return $('.row').last();
  };

  tagLink = function() {
    var $container = this,
        $addButton = $('<button class="btn btn-xs btn-default add-tag"></button>'),
        $a = $('Add tag');

    function startEditing(event) {
      var abortEditing,
          submitTag,
          $thisLi = $(event.target).parent(),
          $tagInput,
          $form;
      event.preventDefault();
      $thisLi.find('*').hide();

      $form = $('<form><input type="submit" class="enter-to-submit"></form>');
      $tagInput = $('<input type="text" class="edit form-control" name="tag" autocapitalize="none">');
      $form.prepend($tagInput);

      abortEditing = catsnap.generateAbortEditing($tagInput, $a.add($addButton), $tagInput);

      submitTag = window.catsnap.generateSubmitTag(
          $form, $container, abortEditing, showError.bind($container), function() {
        var $nextLi = $('
'),
            $removeButton = $('<button class="btn btn-xs btn-default remove-tag">'),
            $xSign = $(''),
            $tag = $(''),
            tagName = $tagInput.val().trim(),
            removeTag,
            newTagLink;

        $thisLi.find('*').remove();

        removeTag = catsnap.generateRemoveTag($container, $thisLi.remove);

        $tag.text(tagName);
        $removeButton.append($xSign);
        $thisLi.append([$removeButton, ' ', $tag]);
        $removeButton.click(removeTag);
        $tag.click(removeTag);

        newTagLink = tagLink.call($container);
        $nextLi.append(newTagLink);
        $container.find('ul').append($nextLi);
      });

      $tagInput.blur(submitTag);
      $form.submit(submitTag);
      catsnap.tagKeyListeners($form, abortEditing, function() {
        $thisLi.siblings().find('a').click();
      });

      $thisLi.append($form);
      $a.parent().append($thisLi);
      $form.find('input').focus();
    }

    $addButton.click(startEditing);
    $a.click(startEditing);

    return [$addButton, ' ', $a];
  };

  showError = function(data) {
    var message = data.responseJSON.error;
    this.find('div.alert').remove();
    this.prepend($('
' + message + '
'));
  };

  checkForImage = function(previousTimeout) {
    var $container = this,
        url = this.data('url'),
        newTimeout = previousTimeout * 1.4,
        $a = $(''),
        $img = $('');

    $img.error(function() {
      $img.off('error');
      $img.error(function() {
        window.setTimeout(checkForImage.bind($container, newTimeout), newTimeout);
      });
      $img.attr('src', url);
    });
    $img.load(function() {
      $container.find('img').remove();
      $a.append($img);
      $container.prepend($a);
    });
    $img.attr('src', url + '_thumbnail');
  };

  saveAlbum = function(event) {
    var $form = $(this),
        $modalHeader = $('#new-album').find('.modal-header'),
        $albumInput = $form.find('input[type="text"]'),
        albumName = $albumInput.val();

    event.preventDefault();

    $.ajax($form.attr('action') + '.json', {
      type: "POST",
      data: {name: albumName},
      success: function(data) {
        var $albumDropdown = $('#album'),
            $modal = $('#new-album'),
            $option;

        $option = $('<option>');
        $option.text(albumName);
        $option.val(data.album_id);
        $albumDropdown.append($option);
        $albumDropdown.val(data.album_id);

        $modalHeader.find('div.alert').remove();
        $albumInput.val('');
        $modal.modal('hide');
      },
      error: showError.bind($modalHeader),
    });
  };

  $('.image-control form').submit(sendImage);
  $('#new-album form').submit(saveAlbum);
  $('input[type="file"]').on('change', function() {
    var numFiles = $(this).prop('files').length,
        displayText = $(this).val();

    if (numFiles > 1) {
      displayText = displayText + ', ' + (numFiles - 1) + ' more';
    }
    $(this).siblings('label').text(displayText);
  });
});
<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

$(function () {

	Asc.spreadsheet_api.prototype._init = function () {
	};
	Asc.spreadsheet_api.prototype._loadFonts = function (fonts, callback) {
		callback();
	};
	AscCommonExcel.WorkbookView.prototype._calcMaxDigitWidth = function () {
	};
	AscCommonExcel.WorkbookView.prototype._init = function () {
	};
	AscCommonExcel.WorkbookView.prototype._onWSSelectionChanged = function () {
	};
	AscCommonExcel.WorkbookView.prototype.showWorksheet = function () {
	};
	AscCommonExcel.WorksheetView.prototype._init = function () {
	};
	AscCommonExcel.WorksheetView.prototype._onUpdateFormatTable = function () {
	};
	AscCommonExcel.WorksheetView.prototype.setSelection = function () {
	};
	AscCommonExcel.WorksheetView.prototype.draw = function () {
	};
	AscCommonExcel.WorksheetView.prototype._prepareDrawingObjects = function () {
	};
	AscCommonExcel.WorksheetView.prototype._reinitializeScroll = function () {
	};
	AscCommon.baseEditorsApi.prototype._onEndLoadSdk = function () {
	};

	var sData = AscCommon.getEmpty();
	var api = new Asc.spreadsheet_api({
		'id-view': 'editor_sdk'
	});
	window["Asc"]["editor"] = api;
	AscCommon.g_oTableId.init();
	api._onEndLoadSdk();
	api._openDocument(sData);
	api._openOnClient();
	api.collaborativeEditing = new AscCommonExcel.CCollaborativeEditing({});
	api.wb = new AscCommonExcel.WorkbookView(api.wbModel, api.controller, api.handlers, api.HtmlElement,
		api.topLineEditorElement, api, api.collaborativeEditing, api.fontRenderingMode);
	var wb = api.wbModel;
	wb.handlers.add("getSelectionState", function () {
		return null;
	});
	api.wb.cellCommentator = new AscCommonExcel.CCellCommentator({
		model: api.wbModel.aWorksheets[0],
		collaborativeEditing: null,
		draw: function() {
		},
		handlers: {
			trigger: function() {
				return false;
			}
		}
	});

	var wsView = api.wb.getWorksheet(0);
	wsView.handlers = api.handlers;
	wsView.objectRender = new AscFormat.DrawingObjects();
	var ws = api.wbModel.aWorksheets[0];

	var getRange = function (c1, r1, c2, r2) {
		return new window["Asc"].Range(c1, r1, c2, r2);
	};

	test("Test: \"simple tests\"", function () {

		ws.getRange2("A1").setValue("-4");

		ws.selectionRange.ranges = [getRange(0, 0, 0, 0)];
		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValue(), ws.getRange2("A1").getValue());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValue(), "-4");
		strictEqual(ws.getRange2("B6").getValue(), "-4");
		strictEqual(ws.getRange2("B7").getValue(), "-4");
		strictEqual(ws.getRange2("B8").getValue(), "-4");
		strictEqual(ws.getRange2("B9").getValue(), "-4");
	});

	test("Test: \"formula tests\"", function () {
		var val = "=SIN(1)";

		ws.getRange2("A1").setValue(val);

		ws.selectionRange.ranges = [getRange(0, 0, 0, 0)];
		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValueForEdit(), ws.getRange2("A1").getValueForEdit());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValueForEdit(), val);
		strictEqual(ws.getRange2("B6").getValueForEdit(), val);
		strictEqual(ws.getRange2("B7").getValueForEdit(), val);
		strictEqual(ws.getRange2("B8").getValueForEdit(), val);
		strictEqual(ws.getRange2("B9").getValueForEdit(), val);

		var val1 = "=SIN(A2)";
		var val2 = "=SIN(A3)";

		ws.getRange2("A1").setValue(val1);
		ws.getRange2("A2").setValue(val2);

		ws.selectionRange.ranges = [getRange(0, 0, 0, 1)];
		base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(2, 1, 2, 6), getRange(3, 5, 3, 8), getRange(4, 5, 4, 7)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("C2").getValueForEdit(), "=SIN(C3)");
		strictEqual(ws.getRange2("C3").getValueForEdit(), "=SIN(C4)");
		strictEqual(ws.getRange2("C4").getValueForEdit(), "=SIN(C5)");
		strictEqual(ws.getRange2("C5").getValueForEdit(), "=SIN(C6)");
		strictEqual(ws.getRange2("C6").getValueForEdit(), "=SIN(C7)");
		strictEqual(ws.getRange2("C7").getValueForEdit(), "=SIN(C8)");

		strictEqual(ws.getRange2("D6").getValueForEdit(), "=SIN(D7)");
		strictEqual(ws.getRange2("D7").getValueForEdit(), "=SIN(D8)");
		strictEqual(ws.getRange2("D8").getValueForEdit(), "=SIN(D9)");
		strictEqual(ws.getRange2("D9").getValueForEdit(), "=SIN(D10)");

		strictEqual(ws.getRange2("E6").getValueForEdit(), "=SIN(E7)");
		strictEqual(ws.getRange2("E7").getValueForEdit(), "=SIN(E8)");
		strictEqual(ws.getRange2("E8").getValueForEdit(), "");
	});

	test("Test: \"comment tests\"", function () {

		ws.getRange2("E10").setValue("-4");
		var comment = new  window["Asc"].asc_CCommentData(null);
		comment.asc_putText("test");
		/*comment.asc_putTime(this.utcDateToString(new Date()));
		comment.asc_putOnlyOfficeTime(this.ooDateToString(new Date()));
		comment.asc_putUserId(this.currentUserId);
		comment.asc_putUserName(this.currentUserName);
		comment.asc_putSolved(false);*/

		ws.selectionRange.ranges = [getRange(0, 0, 0, 0)];
		api.asc_addComment(comment);

		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValue(), ws.getRange2("A1").getValue());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValue(), "-4");
		strictEqual(ws.getRange2("B6").getValue(), "-4");
		strictEqual(ws.getRange2("B7").getValue(), "-4");
		strictEqual(ws.getRange2("B8").getValue(), "-4");
		strictEqual(ws.getRange2("B9").getValue(), "-4");
	});

	module("CopyPaste");
});<commit_msg>[se] Fix tests<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

$(function () {

	Asc.spreadsheet_api.prototype._init = function () {
	};
	Asc.spreadsheet_api.prototype._loadFonts = function (fonts, callback) {
		callback();
	};
	AscCommonExcel.WorkbookView.prototype._calcMaxDigitWidth = function () {
	};
	AscCommonExcel.WorkbookView.prototype._init = function () {
	};
	AscCommonExcel.WorkbookView.prototype._onWSSelectionChanged = function () {
	};
	AscCommonExcel.WorkbookView.prototype.showWorksheet = function () {
	};
	AscCommonExcel.WorksheetView.prototype._init = function () {
	};
	AscCommonExcel.WorksheetView.prototype._onUpdateFormatTable = function () {
	};
	AscCommonExcel.WorksheetView.prototype.setSelection = function () {
	};
	AscCommonExcel.WorksheetView.prototype.draw = function () {
	};
	AscCommonExcel.WorksheetView.prototype._prepareDrawingObjects = function () {
	};
	AscCommonExcel.WorksheetView.prototype._reinitializeScroll = function () {
	};
	AscCommon.baseEditorsApi.prototype._onEndLoadSdk = function () {
	};

	var sData = AscCommon.getEmpty();
	var api = new Asc.spreadsheet_api({
		'id-view': 'editor_sdk'
	});
	window["Asc"]["editor"] = api;
	AscCommon.g_oTableId.init();
	api._onEndLoadSdk();
	api._openDocument(sData);
	api._openOnClient();
	api.collaborativeEditing = new AscCommonExcel.CCollaborativeEditing({});
	api.wb = new AscCommonExcel.WorkbookView(api.wbModel, api.controller, api.handlers, api.HtmlElement,
		api.topLineEditorElement, api, api.collaborativeEditing, api.fontRenderingMode);
	var wb = api.wbModel;
	wb.handlers.add("getSelectionState", function () {
		return null;
	});
	api.wb.cellCommentator = new AscCommonExcel.CCellCommentator({
		model: api.wbModel.aWorksheets[0],
		collaborativeEditing: null,
		draw: function() {
		},
		handlers: {
			trigger: function() {
				return false;
			}
		}
	});

	AscCommonExcel.CCellCommentator.prototype.isLockedComment = function (oComment, callbackFunc) {
		callbackFunc(true);
	};
	AscCommonExcel.CCellCommentator.prototype.drawCommentCells = function () {
	};

	var wsView = api.wb.getWorksheet(0);
	wsView.handlers = api.handlers;
	wsView.objectRender = new AscFormat.DrawingObjects();
	var ws = api.wbModel.aWorksheets[0];

	var getRange = function (c1, r1, c2, r2) {
		return new window["Asc"].Range(c1, r1, c2, r2);
	};

	test("Test: \"simple tests\"", function () {

		ws.getRange2("A1").setValue("-4");

		ws.selectionRange.ranges = [getRange(0, 0, 0, 0)];
		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValue(), ws.getRange2("A1").getValue());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValue(), "-4");
		strictEqual(ws.getRange2("B6").getValue(), "-4");
		strictEqual(ws.getRange2("B7").getValue(), "-4");
		strictEqual(ws.getRange2("B8").getValue(), "-4");
		strictEqual(ws.getRange2("B9").getValue(), "-4");
	});

	test("Test: \"formula tests\"", function () {
		var val = "=SIN(1)";

		ws.getRange2("A1").setValue(val);

		ws.selectionRange.ranges = [getRange(0, 0, 0, 0)];
		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValueForEdit(), ws.getRange2("A1").getValueForEdit());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValueForEdit(), val);
		strictEqual(ws.getRange2("B6").getValueForEdit(), val);
		strictEqual(ws.getRange2("B7").getValueForEdit(), val);
		strictEqual(ws.getRange2("B8").getValueForEdit(), val);
		strictEqual(ws.getRange2("B9").getValueForEdit(), val);

		var val1 = "=SIN(A2)";
		var val2 = "=SIN(A3)";

		ws.getRange2("A1").setValue(val1);
		ws.getRange2("A2").setValue(val2);

		ws.selectionRange.ranges = [getRange(0, 0, 0, 1)];
		base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(2, 1, 2, 6), getRange(3, 5, 3, 8), getRange(4, 5, 4, 7)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("C2").getValueForEdit(), "=SIN(C3)");
		strictEqual(ws.getRange2("C3").getValueForEdit(), "=SIN(C4)");
		strictEqual(ws.getRange2("C4").getValueForEdit(), "=SIN(C5)");
		strictEqual(ws.getRange2("C5").getValueForEdit(), "=SIN(C6)");
		strictEqual(ws.getRange2("C6").getValueForEdit(), "=SIN(C7)");
		strictEqual(ws.getRange2("C7").getValueForEdit(), "=SIN(C8)");

		strictEqual(ws.getRange2("D6").getValueForEdit(), "=SIN(D7)");
		strictEqual(ws.getRange2("D7").getValueForEdit(), "=SIN(D8)");
		strictEqual(ws.getRange2("D8").getValueForEdit(), "=SIN(D9)");
		strictEqual(ws.getRange2("D9").getValueForEdit(), "=SIN(D10)");

		strictEqual(ws.getRange2("E6").getValueForEdit(), "=SIN(E7)");
		strictEqual(ws.getRange2("E7").getValueForEdit(), "=SIN(E8)");
		strictEqual(ws.getRange2("E8").getValueForEdit(), "");
	});

	test("Test: \"comment tests\"", function () {

		ws.getRange2("E10").setValue("-4");
		var comment = new  window["Asc"].asc_CCommentData(null);
		comment.asc_putText("test");
		/*comment.asc_putTime(this.utcDateToString(new Date()));
		comment.asc_putOnlyOfficeTime(this.ooDateToString(new Date()));
		comment.asc_putUserId(this.currentUserId);
		comment.asc_putUserName(this.currentUserName);
		comment.asc_putSolved(false);*/

		ws.selectionRange.ranges = [getRange(4, 9, 4, 9)];
		api.asc_addComment(comment);

		var base64 = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(ws, wsView.objectRender);

		ws.selectionRange.ranges = [getRange(0, 1, 0, 1)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A2").getValue(), ws.getRange2("E10").getValue());

		ws.selectionRange.ranges = [getRange(0, 5, 0, 5), getRange(1, 5, 1, 8)];
		AscCommonExcel.g_clipboardExcel.pasteData(wsView, AscCommon.c_oAscClipboardDataFormat.Internal, base64);

		strictEqual(ws.getRange2("A6").getValue(), "-4");
		strictEqual(ws.getRange2("B6").getValue(), "-4");
		strictEqual(ws.getRange2("B7").getValue(), "-4");
		strictEqual(ws.getRange2("B8").getValue(), "-4");
		strictEqual(ws.getRange2("B9").getValue(), "-4");
	});

	module("CopyPaste");
});<|endoftext|>


<commit_before>/*
 * This is a third-party library module, originally built by the lovely folks at Eris Ltd.
 * SOURCE: https://github.com/eris-ltd/hello-eris/blob/master/js/libs/eris-wrapper.js
 */

/* eslint-disable */

var binstring = require('binstring');
var erisC = require('eris-contracts');
var EventEmitter = require('events');
var util = require('util');
var logger = require(__libs+'/eris/eris-logger');

(function () {

    var log = logger.getLogger('eris.wrapper');

    // EventEmitter
    function ErisEvents() {
        EventEmitter.call(this);
    }

    util.inherits(ErisEvents, EventEmitter);

    /*
     Constructor for a Wrapper instance to talk to a specific chain
     */
    function ErisWrapper(host, port, account) {

        //TODO find a better way to easily test
        account = account || require('../../test/chain-config/accounts.json')[__settings.eris.chain.devAccount];

        var self = this;
        self.erisdbURL = 'http://'+host+':'+port+'/rpc';
        self.contractManager = erisC.newContractManagerDev(self.erisdbURL, account);
        self.listen = new ErisEvents();
    }

    ErisWrapper.prototype.events = {}; //TODO to be defined, e.g. contract added event

    ErisWrapper.prototype.createContract = function(abi, address, jsonOutput) {

        //TODO check inputs, check existing contract at name

        if(log.isDebugEnabled()) {
            log.debug('Creating contract factory with ABI '+ JSON.stringify(abi) +' at address '+ address +'.');
        }
        // instantiate the contract objects using the abi and address
        var contract;
        if(address) {
            contract = this.contractManager.newContractFactory(abi).at(address);
        } else {
            contract = this.contractManager.newContractFactory(abi);
        }
        // Turn on JSON output for bundle contracts
        if(jsonOutput) {
            contract.setOutputFormatter(erisC.outputFormatters.jsonStrings);
        }
        return contract;
    };

    /*
     Wraps the given callback and executes the 'convert' function on the result,
     if there is one, before invoking the callback(error, result).
     */
    var convertibleCallback = function(callback, convert) {
        return function(err, res) {
            callback(err, (res && convert) ? convert(res) : res);
        };
    };

    /* Converts given string to hex */
    var str2hex = function (str) {
        return binstring(str, { in:'binary', out:'hex' });
    };

    /* Converts given hex to string and removes trailing null character */
    var hex2str = function (hexx) {
        return String(Buffer(hexx, 'hex')).replace(/\0/g, '');
    };

    module.exports = {
        'NewWrapper': ErisWrapper,
        'convertibleCallback': convertibleCallback,
        'str2hex': str2hex,
        'hex2str': hex2str
    };

}());
<commit_msg>Tweaks `convertibleCallback` to take a `pipeline` array of transform funcs instead of just one.<commit_after>/*
 * This is a third-party library module (including some small adjustments of my own),
 * originally built by the lovely folks at Eris Ltd.
 * SOURCE: https://github.com/eris-ltd/hello-eris/blob/master/js/libs/eris-wrapper.js
 */

/* eslint-disable */

var binstring = require('binstring');
var erisC = require('eris-contracts');
var EventEmitter = require('events');
var util = require('util');
var logger = require(__libs+'/eris/eris-logger');

(function () {

    var log = logger.getLogger('eris.wrapper');

    // EventEmitter
    function ErisEvents() {
        EventEmitter.call(this);
    }

    util.inherits(ErisEvents, EventEmitter);

    /*
     Constructor for a Wrapper instance to talk to a specific chain
     */
    function ErisWrapper(host, port, account) {

        //TODO find a better way to easily test
        account = account || require('../../test/chain-config/accounts.json')[__settings.eris.chain.devAccount];

        var self = this;
        self.erisdbURL = 'http://'+host+':'+port+'/rpc';
        self.contractManager = erisC.newContractManagerDev(self.erisdbURL, account);
        self.listen = new ErisEvents();
    }

    ErisWrapper.prototype.events = {}; //TODO to be defined, e.g. contract added event

    ErisWrapper.prototype.createContract = function(abi, address, jsonOutput) {

        //TODO check inputs, check existing contract at name

        if(log.isDebugEnabled()) {
            log.debug('Creating contract factory with ABI '+ JSON.stringify(abi) +' at address '+ address +'.');
        }
        // instantiate the contract objects using the abi and address
        var contract;
        if(address) {
            contract = this.contractManager.newContractFactory(abi).at(address);
        } else {
            contract = this.contractManager.newContractFactory(abi);
        }
        // Turn on JSON output for bundle contracts
        if(jsonOutput) {
            contract.setOutputFormatter(erisC.outputFormatters.jsonStrings);
        }
        return contract;
    };

    /**
     * convertibleCallback - Wraps the given callback and executes each
     * conversion function in the `pipeline` array on the result in order,
     * before invoking the callback(error, result).
     *
     * @param  {func} callback description
     * @param  {Array} pipeline description
     * @return {type}          description
     */
    var convertibleCallback = function(callback, pipeline) {
        return function(err, res) {
            if (res && pipeline) {
                pipeline.forEach(function(convFn) { res = convFn(res) });
            }
            callback(err, res);
        };
    };

    /* Converts given string to hex */
    var str2hex = function (str) {
        return binstring(str, { in:'binary', out:'hex' });
    };

    /* Converts given hex to string and removes trailing null character */
    var hex2str = function (hexx) {
        return String(Buffer(hexx, 'hex')).replace(/\0/g, '');
    };

    module.exports = {
        'NewWrapper': ErisWrapper,
        'convertibleCallback': convertibleCallback,
        'str2hex': str2hex,
        'hex2str': hex2str
    };

}());
<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on filters, and services
angular.module('lexicon',
  [
    'ngRoute',
    'ngSanitize',
    'lexicon.edit',
    'meaning',
    'examples',
    'bellows.services',
    'bellows.filters',
    'lexicon.add-meanings',
    'lexicon.configuration',
    'lexicon.view.settings',
    'lexicon.import-export',
    'lexicon.settings',
    'lexicon.manage-users',
    'lexicon.services',
    'lexicon.filters',
    'pascalprecht.translate'
  ])
  .config(['$routeProvider', '$translateProvider', function ($routeProvider, $translateProvider) {

    // configure interface language filepath
    $translateProvider.useStaticFilesLoader({
      prefix: '/angular-app/languageforge/lexicon/lang/',
      suffix: '.json'
    });
    $translateProvider.preferredLanguage('en');

    // The "projects" route is a hack to redirect to the /app/projects URL.
    // See "otherwise" route below
    $routeProvider.when('/projects', { template: ' ', controller: function () {
      window.location.replace('/app/projects'); } });

    $routeProvider.when('/', { redirectTo: '/dbe' });
    $routeProvider.when('/view',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/gatherTexts',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/review',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/wordlist',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });

    $routeProvider.when(
      '/dbe',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/dbe/:entryId',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/dbe/:entryId/comments',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-grammar',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-examples',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-meanings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/configuration',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/configuration.html'
      }
    );
    $routeProvider.when(
      '/viewSettings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/view-settings.html'
      }
    );
    $routeProvider.when(
      '/importExport',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/import-export.html'
      }
    );
    $routeProvider.when(
      '/settings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/settings.html'
      }
    );
    $routeProvider.when(
      '/users',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/manage-users.html'
      }
    );
    $routeProvider.otherwise({ redirectTo: '/dbe' });
  }])
  .controller('MainCtrl', ['$scope', 'sessionService', 'lexConfigService', 'lexProjectService',
    '$translate', '$location', '$interval', 'silNoticeService', 'lexEditorDataService',
    'lexSendReceiveApi', 'lexSendReceive',
  function ($scope, sessionService, lexConfig, lexProjectService,
            $translate, $location, $interval, notice, editorService,
            sendReceiveApi, sendReceive) {
    var pristineLanguageCode;

    $scope.project = sessionService.session.project;
    $scope.projectSettings = sessionService.session.projectSettings;
    $scope.syncNotice = sendReceive.syncNotice;

    $scope.rights = {};
    $scope.rights.canRemoveUsers = function canRemoveUsers() {
      if (sendReceive.isInProgress()) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
        sessionService.operation.DELETE);
    };

    $scope.rights.canCreateUsers = function canCreateUsers() {
      if (sendReceive.isInProgress()) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
          sessionService.operation.CREATE);
    };

    $scope.rights.canEditUsers = function canEditUsers() {
      if (sendReceive.isInProgress()) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
          sessionService.operation.EDIT);
    };

    $scope.rights.canArchiveProject = function canArchiveProject() {
      if (sendReceive.isInProgress() ||
          !angular.isDefined(sessionService.session.project)) return false;

      return (sessionService.hasProjectRight(sessionService.domain.PROJECTS, sessionService.operation.ARCHIVE_OWN) ||
              sessionService.hasSiteRight(sessionService.domain.PROJECTS, sessionService.operation.ARCHIVE));
    };

    $scope.rights.showControlBar = function showControlBar() {
      return $scope.rights.canRemoveUsers() || $scope.rights.canCreateUsers() ||
        $scope.rights.canEditUsers();
    };

    $scope.finishedLoading = false;
    editorService.loadEditorData().then(function () {
      $scope.finishedLoading = true;
      sendReceive.checkInitialState();
    });

    $scope.currentUserRole = sessionService.session.projectSettings.currentUserRole;
    $scope.interfaceConfig = sessionService.session.projectSettings.interfaceConfig;
    pristineLanguageCode = angular.copy($scope.interfaceConfig.userLanguageCode);
    changeInterfaceLanguage($scope.interfaceConfig.userLanguageCode);

    $scope.gotoDictionary = function gotoDictionary() {
      $location.path('/dbe');
    };

    $scope.showDictionaryButton = function showDictionaryButton() {
      return !($location.path().indexOf('/dbe') == 0);
    };

    function changeInterfaceLanguage(code) {
      $translate.use(code);
      pristineLanguageCode = angular.copy(code);

      if (InputSystems.isRightToLeft(code)) {
        $scope.interfaceConfig.direction = 'rtl';
        $scope.interfaceConfig.pullToSide = 'pull-left';
        $scope.interfaceConfig.pullNormal = 'pull-right';
        $scope.interfaceConfig.placementToSide = 'right';
        $scope.interfaceConfig.placementNormal = 'left';
      } else {
        $scope.interfaceConfig.direction = 'ltr';
        $scope.interfaceConfig.pullToSide = 'pull-right';
        $scope.interfaceConfig.pullNormal = 'pull-left';
        $scope.interfaceConfig.placementToSide = 'left';
        $scope.interfaceConfig.placementNormal = 'right';
      }
    }

    $scope.$watch('interfaceConfig.userLanguageCode', function (newVal) {
      if (newVal && newVal != pristineLanguageCode) {
        var user = {};
        user.interfaceLanguageCode = newVal;

        lexProjectService.updateUserProfile(user);

        changeInterfaceLanguage(newVal);
      }
    });

    $scope.showSyncButton = function showSyncButton() {
      var isDbeView = ($location.path().indexOf('/dbe') == 0);
      return $scope.rights.canEditUsers() && $scope.projectSettings.hasSendReceive && isDbeView;
    };

    $scope.syncProject = function syncProject() {
      sendReceiveApi.receiveProject(function (result) {
        if (result.ok) {
          sendReceive.setSyncStarted();
        } else {
          notice.push(notice.ERROR,
            'The project could not be synchronized with LanguageDepot.org. Please try again.');
        }
      });
    };

    $scope.$on('$destroy', sendReceive.cancelAllStatusTimers);
    $scope.$on('$locationChangeStart', sendReceive.cancelAllStatusTimers);

    // setup offline.js options
    // see https://github.com/hubspot/offline for all options
    // we tell offline.js to NOT store and remake requests while the connection is down
    Offline.options.requests = false;
    Offline.options.checkOnLoad = true;
    Offline.options.checks = { xhr: { url: '/offlineCheck.txt' } };

    var offlineMessageId;
    Offline.on('up', function () {
      if ($scope.online == false) {
        notice.removeById(offlineMessageId);
        notice.push(notice.SUCCESS, 'You are back online!');
      }

      $scope.online = true;
      $scope.$digest();
    });

    Offline.on('down', function () {
      offlineMessageId = notice.push(notice.ERROR,
        'You are offline.  Some features are not available', null, true);
      $scope.online = false;
      if (!/^dbe/.test($location.path())) {
        // redirect to the dbe
        $location.path('/dbe');
        notice.push(notice.SUCCESS,
          'The dictionary editor is available offline.  Settings are not.');
      }

      $scope.$digest();
    });

  }])
  .controller('BreadcrumbCtrl', ['$scope', '$rootScope', 'breadcrumbService',
  function ($scope, $rootScope, breadcrumbService) {
    $scope.idmap = breadcrumbService.idmap;
    $rootScope.$on('$routeChangeSuccess', function () {
      $scope.breadcrumbs = breadcrumbService.read();
    });

    $scope.$watch('idmap', function () {
      $scope.breadcrumbs = breadcrumbService.read();
    }, true);
  }])

  ;
<commit_msg>Make LF UI readonly for archived projects (part 2)<commit_after>'use strict';

// Declare app level module which depends on filters, and services
angular.module('lexicon',
  [
    'ngRoute',
    'ngSanitize',
    'lexicon.edit',
    'meaning',
    'examples',
    'bellows.services',
    'bellows.filters',
    'lexicon.add-meanings',
    'lexicon.configuration',
    'lexicon.view.settings',
    'lexicon.import-export',
    'lexicon.settings',
    'lexicon.manage-users',
    'lexicon.services',
    'lexicon.filters',
    'pascalprecht.translate'
  ])
  .config(['$routeProvider', '$translateProvider', function ($routeProvider, $translateProvider) {

    // configure interface language filepath
    $translateProvider.useStaticFilesLoader({
      prefix: '/angular-app/languageforge/lexicon/lang/',
      suffix: '.json'
    });
    $translateProvider.preferredLanguage('en');

    // The "projects" route is a hack to redirect to the /app/projects URL.
    // See "otherwise" route below
    $routeProvider.when('/projects', { template: ' ', controller: function () {
      window.location.replace('/app/projects'); } });

    $routeProvider.when('/', { redirectTo: '/dbe' });
    $routeProvider.when('/view',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/gatherTexts',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/review',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });
    $routeProvider.when('/wordlist',
      { templateUrl: '/angular-app/languageforge/lexicon/views/not-implemented.html' });

    $routeProvider.when(
      '/dbe',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/dbe/:entryId',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/dbe/:entryId/comments',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-grammar',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-examples',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/add-meanings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/edit.html'
      }
    );
    $routeProvider.when(
      '/configuration',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/configuration.html'
      }
    );
    $routeProvider.when(
      '/viewSettings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/view-settings.html'
      }
    );
    $routeProvider.when(
      '/importExport',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/import-export.html'
      }
    );
    $routeProvider.when(
      '/settings',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/settings.html'
      }
    );
    $routeProvider.when(
      '/users',
      {
        templateUrl: '/angular-app/languageforge/lexicon/views/manage-users.html'
      }
    );
    $routeProvider.otherwise({ redirectTo: '/dbe' });
  }])
  .controller('MainCtrl', ['$scope', 'sessionService', 'lexConfigService', 'lexProjectService',
    '$translate', '$location', '$interval', 'silNoticeService', 'lexEditorDataService',
    'lexSendReceiveApi', 'lexSendReceive',
  function ($scope, sessionService, lexConfig, lexProjectService,
            $translate, $location, $interval, notice, editorService,
            sendReceiveApi, sendReceive) {
    var pristineLanguageCode;

    $scope.project = sessionService.session.project;
    $scope.projectSettings = sessionService.session.projectSettings;
    $scope.syncNotice = sendReceive.syncNotice;

    $scope.rights = {};
    $scope.rights.canRemoveUsers = function canRemoveUsers() {
      if (sendReceive.isInProgress()) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
        sessionService.operation.DELETE);
    };

    $scope.rights.canCreateUsers = function canCreateUsers() {
      if (sendReceive.isInProgress()) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
          sessionService.operation.CREATE);
    };

    $scope.rights.canEditUsers = function canEditUsers() {
      if (sendReceive.isInProgress() || sessionService.session.project.isArchived) return false;

      return sessionService.hasProjectRight(sessionService.domain.USERS,
          sessionService.operation.EDIT);
    };

    $scope.rights.canArchiveProject = function canArchiveProject() {
      if (sendReceive.isInProgress() || !angular.isDefined(sessionService.session.project)) return false;

      return (sessionService.hasProjectRight(sessionService.domain.PROJECTS, sessionService.operation.ARCHIVE_OWN) ||
              sessionService.hasSiteRight(sessionService.domain.PROJECTS, sessionService.operation.ARCHIVE));
    };

    $scope.rights.showControlBar = function showControlBar() {
      return $scope.rights.canRemoveUsers() || $scope.rights.canCreateUsers() ||
        $scope.rights.canEditUsers();
    };

    $scope.finishedLoading = false;
    editorService.loadEditorData().then(function () {
      $scope.finishedLoading = true;
      sendReceive.checkInitialState();
    });

    $scope.currentUserRole = sessionService.session.projectSettings.currentUserRole;
    $scope.interfaceConfig = sessionService.session.projectSettings.interfaceConfig;
    pristineLanguageCode = angular.copy($scope.interfaceConfig.userLanguageCode);
    changeInterfaceLanguage($scope.interfaceConfig.userLanguageCode);

    $scope.gotoDictionary = function gotoDictionary() {
      $location.path('/dbe');
    };

    $scope.showDictionaryButton = function showDictionaryButton() {
      return !($location.path().indexOf('/dbe') == 0);
    };

    function changeInterfaceLanguage(code) {
      $translate.use(code);
      pristineLanguageCode = angular.copy(code);

      if (InputSystems.isRightToLeft(code)) {
        $scope.interfaceConfig.direction = 'rtl';
        $scope.interfaceConfig.pullToSide = 'pull-left';
        $scope.interfaceConfig.pullNormal = 'pull-right';
        $scope.interfaceConfig.placementToSide = 'right';
        $scope.interfaceConfig.placementNormal = 'left';
      } else {
        $scope.interfaceConfig.direction = 'ltr';
        $scope.interfaceConfig.pullToSide = 'pull-right';
        $scope.interfaceConfig.pullNormal = 'pull-left';
        $scope.interfaceConfig.placementToSide = 'left';
        $scope.interfaceConfig.placementNormal = 'right';
      }
    }

    $scope.$watch('interfaceConfig.userLanguageCode', function (newVal) {
      if (newVal && newVal != pristineLanguageCode) {
        var user = {};
        user.interfaceLanguageCode = newVal;

        lexProjectService.updateUserProfile(user);

        changeInterfaceLanguage(newVal);
      }
    });

    $scope.showSyncButton = function showSyncButton() {
      var isDbeView = ($location.path().indexOf('/dbe') == 0);
      return !$scope.project.isArchived && $scope.rights.canEditUsers() && $scope.projectSettings.hasSendReceive && isDbeView;
    };

    $scope.syncProject = function syncProject() {
      sendReceiveApi.receiveProject(function (result) {
        if (result.ok) {
          sendReceive.setSyncStarted();
        } else {
          notice.push(notice.ERROR,
            'The project could not be synchronized with LanguageDepot.org. Please try again.');
        }
      });
    };

    $scope.$on('$destroy', sendReceive.cancelAllStatusTimers);
    $scope.$on('$locationChangeStart', sendReceive.cancelAllStatusTimers);

    // setup offline.js options
    // see https://github.com/hubspot/offline for all options
    // we tell offline.js to NOT store and remake requests while the connection is down
    Offline.options.requests = false;
    Offline.options.checkOnLoad = true;
    Offline.options.checks = { xhr: { url: '/offlineCheck.txt' } };

    var offlineMessageId;
    Offline.on('up', function () {
      if ($scope.online == false) {
        notice.removeById(offlineMessageId);
        notice.push(notice.SUCCESS, 'You are back online!');
      }

      $scope.online = true;
      $scope.$digest();
    });

    Offline.on('down', function () {
      offlineMessageId = notice.push(notice.ERROR,
        'You are offline.  Some features are not available', null, true);
      $scope.online = false;
      if (!/^dbe/.test($location.path())) {
        // redirect to the dbe
        $location.path('/dbe');
        notice.push(notice.SUCCESS,
          'The dictionary editor is available offline.  Settings are not.');
      }

      $scope.$digest();
    });

  }])
  .controller('BreadcrumbCtrl', ['$scope', '$rootScope', 'breadcrumbService',
  function ($scope, $rootScope, breadcrumbService) {
    $scope.idmap = breadcrumbService.idmap;
    $rootScope.$on('$routeChangeSuccess', function () {
      $scope.breadcrumbs = breadcrumbService.read();
    });

    $scope.$watch('idmap', function () {
      $scope.breadcrumbs = breadcrumbService.read();
    }, true);
  }])

  ;
<|endoftext|>


<commit_before>var assert   = require('assert');
var validate = require('../index');

describe('JSON', function(){

	var file = {
		name: 'task-rest_bold.json',
		relativePath: '/task-rest_bold.json'
	};

	it('should catch missing closing brackets', function(){
		validate.JSON(file, '{', function (issues) {
			assert(issues && issues.length > 0);
		});
	});

	it('sidecars should have key/value pair for "RepetitionTime" expressed in seconds', function(){
		var jsonObj = '{"RepetitionTime": 1.2, "echo_time": 0.005, "flip_angle": 90, "TaskName": "Rest"}';
		validate.JSON(file, jsonObj, function (issues) {
			assert(issues.length === 0);
		});
		var jsonObjInval = '{"RepetitionTime": 1200, "echo_time": 0.005, "flip_angle": 90, "TaskName": "Rest"}';
		validate.JSON(file, jsonObjInval, function (issues) {
			assert(issues && issues.length === 1);
		});
	});
});
<commit_msg>Add test for SliceTiming negative value detection<commit_after>var assert   = require('assert');
var validate = require('../index');

describe('JSON', function(){

	var file = {
		name: 'task-rest_bold.json',
		relativePath: '/task-rest_bold.json'
	};

	it('should catch missing closing brackets', function(){
		validate.JSON(file, '{', function (issues) {
			assert(issues && issues.length > 0);
		});
	});

	it('sidecars should have key/value pair for "RepetitionTime" expressed in seconds', function(){
		var jsonObj = '{"RepetitionTime": 1.2, "echo_time": 0.005, "flip_angle": 90, "TaskName": "Rest"}';
		validate.JSON(file, jsonObj, function (issues) {
			assert(issues.length === 0);
		});
		var jsonObjInval = '{"RepetitionTime": 1200, "echo_time": 0.005, "flip_angle": 90, "TaskName": "Rest"}';
		validate.JSON(file, jsonObjInval, function (issues) {
			assert(issues && issues.length === 1);
		});
	});

	it('should detect negative value for SliceTiming', function(){
		var jsonObj = '{"SliceTiming": [-1.0, 0.0, 1.0]}';
		validate.JSON(file, jsonObj, function (issues) {
			assert(issues.length === 1 && issues[0].code == 55);
		});
	});
});
<|endoftext|>


<commit_before>import commitsGet from '../helpers/commitsGet';
import cacheCreate from '../helpers/cacheCreate';
import commitsChildrenGet from '../helpers/commitsChildrenGet';
import _ from 'underscore';
import config from '../../config';

let cache = cacheCreate();

export default function(req, res) {
  let workitemNumbers = req.query.numbers || '';
  let instanceId = req.instance.instanceId;

  let buildUri = (page) =>
    req.href('/api/' + instanceId + '/commits/tags/versionone/workitem?numbers=' +
      workitemNumbers + '&page=' + page + '&apiKey=' + req.instance.apiKey);

  let workitemNumbersArray = workitemNumbers.split(',');

  if (workitemNumbersArray.length === 1) {
    let stream = 'versionOne_CommitsWithWorkitems-' + instanceId + '_' + workitemNumbers;

    commitsGet(req.query, stream, buildUri, cache).then(function(commits) {
      // TODO use hal?
      res.send(commits);
    });
  } else if (config.showChildrenFeatureToggle) {
    let streams = [];
    _.each(workitemNumbersArray, function(e, i) {
      streams.push('versionOne_CommitsWithWorkitems-' + instanceId + '_' + e);
    });
    commitsChildrenGet(req.query, streams, buildUri).then(function(commits) {
      res.send(commits);
    });
  } else {
    // Daniel says OK to send empty array here (9/24/2015)
    res.send({commits:[]});
  }
};<commit_msg>S-1036: let to const changes<commit_after>import commitsGet from '../helpers/commitsGet';
import cacheCreate from '../helpers/cacheCreate';
import commitsChildrenGet from '../helpers/commitsChildrenGet';
import _ from 'underscore';
import config from '../../config';

const cache = cacheCreate();

export default function(req, res) {
  const workitemNumbers = req.query.numbers || '';
  const instanceId = req.instance.instanceId;

  const buildUri = page => req.href(`/api/${instanceId}/commits/tags/versionone/workitem?numbers=${workitemNumbers}&page=${page}&apiKey=${req.instance.apiKey}`);

  const workitemNumbersArray = workitemNumbers.split(',');

  if (workitemNumbersArray.length === 1) {
    const stream = `versionOne_CommitsWithWorkitems-${instanceId}_${workitemNumbers}`;

    commitsGet(req.query, stream, buildUri, cache).then(function(commits) {
      // TODO use hal?
      res.send(commits);
    });
  } else if (config.showChildrenFeatureToggle) {
    let streams = [];
    _.each(workitemNumbersArray, function(e, i) {
      streams.push('versionOne_CommitsWithWorkitems-' + instanceId + '_' + e);
    });
    commitsChildrenGet(req.query, streams, buildUri).then(function(commits) {
      res.send(commits);
    });
  } else {
    // Daniel says OK to send empty array here (9/24/2015)
    res.send({commits:[]});
  }
};<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import { generateMap } from 'base/shared/ModelHelper';
import { WeatherStationsModel, ForecastModel, WeatherStationDetailsModel } from '../models';
import  config  from '../config';

export default {

  fetchWeatherStations() {

    const urlApi = config.WEATHER_API_URL +
      '/station/find?lat=40.4165000&lon=-3.7025600&cnt=300&units=metric&appid=' +
       config.WEATHER_API_KEY;
    return fetch(urlApi)
    .then(req => req.json())
    .then(data => {
      for (let i = 0; i < data.length; i++) {
        data[i].id = i + 1;
        data[i].stationId = data[i].station.id;
        if (data[i].station.coord.lng){
          data[i].station.coord.lon = data[i].station.coord.lng;
        }
      }
      return generateMap(data, WeatherStationsModel);
    });
  },

  fetchWeatherStation(id) {
    const urlApi = config.WEATHER_API_URL +
      '/station?id=' + id + '&units=metric&appid=' +
       config.WEATHER_API_KEY;
    return fetch(urlApi)
    .then(req => req.json())
    .then(data => {
      const dataParsed = this.getDataWeatherStation(data);
      return generateMap(dataParsed, WeatherStationDetailsModel);
    } );
  },

  fetchWeather(lat, lng) {

    let urlCall = config.WEATHER_API_URL +
      '/forecast/daily?lat=' +
      lat +'&lon='+
      lng + '&cnt=8&lang=es&units=metric&appid=' +
      config.WEATHER_API_KEY;

    return fetch(urlCall)
    .then(req => req.json())
    .then(data => {
      for (let i=0; i<data.list.length; i++) {
        data.list[i].id = i + 1;
      }
      return generateMap(data.list, ForecastModel);
    });

  },

  getDataWeatherStation(data) {
    let obj = {};
    if (data.params.indexOf('temp') > -1) {
      obj.temp = data.last.main.temp;
    }

    if (data.params.indexOf('humidity') > -1) {
      obj.humidity = data.last.main.humidity;
    }

    if (data.params.indexOf('pressure') > -1) {
      obj.pressure = data.last.main.pressure;
    }

    if (data.params.indexOf('wind') > -1) {
      obj.wind = data.last.wind;
    }

    if (data.params.indexOf('visibility') > -1) {
      obj.visibility = data.last.visibility;
    }

    if (data.params.indexOf('rain') > -1) {
      obj.rain = data.last.rain;
    }

    obj.id = data.station.id;
    obj.dt = data.last.dt;

    let list = [obj];

    return list;

  }

};

<commit_msg>fix lint<commit_after>import fetch from 'isomorphic-fetch';
import { generateMap } from 'base/shared/ModelHelper';
import { WeatherStationsModel, ForecastModel, WeatherStationDetailsModel } from '../models';
import  config  from '../config';

export default {

  fetchWeatherStations() {

    const urlApi = config.WEATHER_API_URL +
      '/station/find?lat=40.4165000&lon=-3.7025600&cnt=300&units=metric&appid=' +
       config.WEATHER_API_KEY;
    return fetch(urlApi)
    .then(req => req.json())
    .then(data => {
      for (let i = 0; i < data.length; i++) {
        data[i].id = i + 1;
        data[i].stationId = data[i].station.id;
        if (data[i].station.coord.lng) {
          data[i].station.coord.lon = data[i].station.coord.lng;
        }
      }
      return generateMap(data, WeatherStationsModel);
    });
  },

  fetchWeatherStation(id) {
    const urlApi = config.WEATHER_API_URL +
      '/station?id=' + id + '&units=metric&appid=' +
       config.WEATHER_API_KEY;
    return fetch(urlApi)
    .then(req => req.json())
    .then(data => {
      const dataParsed = this.getDataWeatherStation(data);
      return generateMap(dataParsed, WeatherStationDetailsModel);
    } );
  },

  fetchWeather(lat, lng) {

    let urlCall = config.WEATHER_API_URL +
      '/forecast/daily?lat=' +
      lat +'&lon='+
      lng + '&cnt=8&lang=es&units=metric&appid=' +
      config.WEATHER_API_KEY;

    return fetch(urlCall)
    .then(req => req.json())
    .then(data => {
      for (let i=0; i<data.list.length; i++) {
        data.list[i].id = i + 1;
      }
      return generateMap(data.list, ForecastModel);
    });

  },

  getDataWeatherStation(data) {
    let obj = {};
    if (data.params.indexOf('temp') > -1) {
      obj.temp = data.last.main.temp;
    }

    if (data.params.indexOf('humidity') > -1) {
      obj.humidity = data.last.main.humidity;
    }

    if (data.params.indexOf('pressure') > -1) {
      obj.pressure = data.last.main.pressure;
    }

    if (data.params.indexOf('wind') > -1) {
      obj.wind = data.last.wind;
    }

    if (data.params.indexOf('visibility') > -1) {
      obj.visibility = data.last.visibility;
    }

    if (data.params.indexOf('rain') > -1) {
      obj.rain = data.last.rain;
    }

    obj.id = data.station.id;
    obj.dt = data.last.dt;

    let list = [obj];

    return list;

  }

};

<|endoftext|>


<commit_before>(function (window) {
  "use strict";

  var self;

  function ImageViewer(canvasId, imageUrl, options){
    self = this;

    options = (typeof options === 'object') ? options : {};

    // canvas
    this.canvas = document.getElementById(canvasId);
    this.context = this.canvas.getContext("2d");

    // dirty state
    this.dirty = true;

    // image scale
    this.scale = 1;
    this.scaleStep = 0.1;

    // image center (scroll offset)
    this.center = { x: 0, y: 0 };

    // image
    this.image = new Image();
    this.image.addEventListener('load', this._onImageLoad, false);
    this.image.src = imageUrl;

    // buttons
    this.buttons = [];

    // add buttons
    var padding = 10
      , radius = 20
      , x = this.canvas.width - radius - padding
      , y = this.canvas.height - radius - padding;

    var plusButton = new Button(x, y - 50, radius, drawPlusIcon);
    plusButton.onClick = function(){ self.zoomIn(); };
    this.buttons.push(plusButton);

    var minusButton = new Button(x, y, radius, drawMinusIcon);
    minusButton.onClick = function(){ self.zoomOut(); };
    this.buttons.push(minusButton);

    // setup target feature
    this.targetFeatureEnabled = (typeof options.target === 'boolean') ? options.target : false;
    this.targetSettingMode = false;
    this.target = null;
    this.targetButtons = [];

    // add target button
    var addTargetButton = new Button(x, y - 150, radius, drawTargetIcon);
    // onclick: toggle targetSettingMode
    addTargetButton.onClick = function(){
      addTargetButton.enabled = self.targetSettingMode = !self.targetSettingMode;
      self.dirty = true;
    };
    this.targetButtons.push(addTargetButton);

    // delete target button
    var deleteTargetButton = new Button(x, y - 100, radius, drawCrossIcon);
    deleteTargetButton.onClick = function(){
      self.target = null;
      self.dirty = true;
    };
    this.targetButtons.push(deleteTargetButton);

    // if target feature was enabled in the options, start it
    if(this.targetFeatureEnabled) this.enableTargetMode();

    // render loop
    this.FPS = 1000/30;
    this.tickInterval = null;

    this.InputHandler = new InputHandler(this.canvas, this);
  }

  ImageViewer.prototype._onImageLoad = function(){
    // set scale to use as much space inside the canvas as possible
    if(((self.canvas.height / self.image.height) * self.image.width) <= self.canvas.width){
      self.scale = self.canvas.height / self.image.height;
    } else {
      self.scale = self.canvas.width / self.image.width;
    }

    // center at image center
    self.center.x = self.image.width / 2;
    self.center.y = self.image.height / 2;

    // image changed
    self.dirty = true;

    // stop old render loop (if existed)
    if(self.tickInterval) clearInterval(self.tickInterval);

    // start new render loop
    self.tickInterval = setInterval(function(){ self._render(); }, self.FPS);
  };

  ImageViewer.prototype._render = function(){
    // check if dirty
    if(!this.dirty) return;
    this.dirty = false;

    var ctx = this.context;
    // clear canvas
    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

    // draw image (transformed and scaled)
    ctx.save();
    var translateX = this.canvas.width / 2 - this.center.x * this.scale
      , translateY = this.canvas.height / 2 - this.center.y * this.scale;

    ctx.translate(translateX, translateY);
    ctx.scale(this.scale, this.scale);

    ctx.drawImage(this.image, 0,0);

    ctx.restore();

    // draw buttons
    this.buttons.forEach(function(button){
      button.draw(ctx);
    });

    // draw target
    if(this.target !== null){
      this._drawTarget();
    }
  };

  ImageViewer.prototype.enableTargetMode = function(){
    this.buttons = this.buttons.concat(this.targetButtons);
    this.targetFeatureEnabled = true;
    this.dirty = true;
  };

  ImageViewer.prototype.disableTargetMode = function(){
    this.buttons = this.buttons.filter(function(b){ return self.targetButtons.indexOf(b) < 0; });
    this.targetFeatureEnabled = false;
    this.targetSettingMode = false;
    this.target = null;
    this.dirty = true;
  };

  ImageViewer.prototype._drawTarget = function(){
    var ctx = this.context;

    ctx.save();

    var shapeScale = 1.5
      , xTranslation = (
                          this.target.x  // x-pos of target on picture
                        + this.canvas.width / this.scale / 2 // offset of scaled canvas
                        - this.center.x // scroll offset of image
                       ) * this.scale // scale the transformation

      , yTranslation = (
                          this.target.y  // y-pos of target on picture
                        + this.canvas.height / this.scale / 2 // offset of scaled canvas
                        - this.center.y // scroll offset of image
                       ) * this.scale // scale the transformation
      ;
    ctx.translate(xTranslation, yTranslation);

    ctx.scale(shapeScale * this.scale, shapeScale * this.scale);
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#ff0000';
    ctx.fillStyle = '#ff0000';

    // flag
    ctx.beginPath();
    ctx.moveTo(0, -20);
    ctx.lineTo(15, -15);
    ctx.lineTo(15, -25);
    ctx.lineTo(0, -30);
    ctx.lineTo(0, 0);
    ctx.stroke();

    // bulls-eye
    // inner circle
    ctx.beginPath();
    ctx.arc(0, 0, 5, 0, 2 * Math.PI, false);
    ctx.stroke();
    // outer circle
    ctx.beginPath();
    ctx.arc(0, 0, 10, 0, 2 * Math.PI, false);
    ctx.stroke();

    ctx.restore();
  };

  ImageViewer.prototype.zoomIn = function(){
    this.scale = this.scale * (1 + this.scaleStep);
    this.dirty = true;
  };

  ImageViewer.prototype.zoomOut = function(){
    this.scale = this.scale * (1 - this.scaleStep);
    this.dirty = true;
  };

  function Button(x, y, radius, icon){
    // centre coordinates
    this.x = x;
    this.y = y;

    // radius
    this.radius = radius;

    // transparency
    this.alpha = 0.5;

    // color
    this.color = '#000000';

    // icon drawing function
    // (ctx, x, y, radius, icon, color, alpha)
    this.icon = icon;

    // enabled state
    this.enabled = false;
    this.enabledAlpha = 0.7;

    // click action
    this.onClick = function(){ alert('no click action set!'); };
  }

  Button.prototype.isWithinBounds = function(x, y){
    var dx = Math.abs(this.x - x)
      , dy = Math.abs(this.y - y);
    return  dx * dx + dy * dy <= this.radius * this.radius;
  };

  Button.prototype.draw = function(ctx){
    // preserve context
    ctx.save();

    // drawing settings
    ctx.globalAlpha = (this.enabled) ? this.enabledAlpha : this.alpha;
    ctx.fillStyle= this.color;
    ctx.lineWidth = 0;

    // draw circle
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fill();

    // draw icon
    ctx.save();
    ctx.globalCompositeOperation = 'destination-out';
    this.icon(ctx, this.x, this.y, this.radius);
    ctx.restore();

    // restore context
    ctx.restore();
  };

  function drawMinusIcon(ctx, centerX, centerY, buttonRadius){
    var rectLength = buttonRadius
      , rectThickness = rectLength / 4
      , x = centerX - rectLength / 2
      , y = centerY - rectThickness / 2;

    ctx.fillRect(x, y, rectLength, rectThickness);
  }

  function drawPlusIcon(ctx, centerX, centerY, buttonRadius){
    /*
        11---10
        |     |
    01--12    09--08
    |              |
    02--03    06--07
        |     |
        04---05
    */
    var rectLength = buttonRadius
      , rectThickness = rectLength / 4;

    ctx.beginPath();
    // 1
    ctx.moveTo(centerX - rectLength / 2,
               centerY - rectThickness / 2);
    // 2
    ctx.lineTo(centerX - rectLength / 2,
               centerY + rectThickness / 2);
    // 3
    ctx.lineTo(centerX - rectThickness / 2,
               centerY + rectThickness / 2);
    // 4
    ctx.lineTo(centerX - rectThickness / 2,
               centerY + rectLength / 2);
    // 5
    ctx.lineTo(centerX + rectThickness / 2,
               centerY + rectLength / 2);
    // 6
    ctx.lineTo(centerX + rectThickness / 2,
               centerY + rectThickness / 2);
    // 7
    ctx.lineTo(centerX + rectLength / 2,
               centerY + rectThickness / 2);
    // 8
    ctx.lineTo(centerX + rectLength / 2,
               centerY - rectThickness / 2);
    // 9
    ctx.lineTo(centerX + rectThickness / 2,
               centerY - rectThickness / 2);
    // 10
    ctx.lineTo(centerX + rectThickness / 2,
               centerY - rectLength / 2);
    // 11
    ctx.lineTo(centerX - rectThickness / 2,
               centerY - rectLength / 2);
    // 12
    ctx.lineTo(centerX - rectThickness / 2,
               centerY - rectThickness / 2);

    ctx.closePath();
    ctx.fill();
  }

  function drawTargetIcon(ctx, centerX, centerY, buttonRadius){
    ctx.lineWidth = buttonRadius * 0.3;
    ctx.strokeStyle = self.color;
    ctx.beginPath();
    ctx.arc(centerX, centerY, buttonRadius * 0.5, 0, 2 * Math.PI);
    ctx.stroke();
  }

  function drawCrossIcon(ctx, centerX, centerY, buttonRadius){
    ctx.save();
      ctx.translate(centerX, centerY + buttonRadius * 0.7);
      ctx.save();
        ctx.rotate(Math.PI / 4);
        drawPlusIcon(ctx, - buttonRadius / 2, - buttonRadius / 2, buttonRadius);
      ctx.restore();
    ctx.restore();
  }

  function InputHandler(canvas, imageViewer) {
    this.canvas = canvas;
    this.imageViewer = imageViewer;

    // global
    this.leftMouseButtonDown = false;
    document.addEventListener('mousedown', this._onMouseDown);
    document.addEventListener('mouseup', this._onMouseUp);

    // zooming
    this.canvas.addEventListener('DOMMouseScroll', this._onMouseWheel);
    this.canvas.addEventListener('mousewheel', this._onMouseWheel);

    // moving
    this.mouseLastPos = null;
    this.canvas.addEventListener('mousemove', this._onMouseMove);

    // set target
    this.canvas.addEventListener('click', this._targetClick);
  }

  InputHandler.prototype._catchButtonClick = function(evt, executeButton){
    var _executeButton = (executeButton === false) ? false : true;
    // check if a button was clicked
    var rect = self.canvas.getBoundingClientRect()
      , pos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    var clickedButtons = self.buttons.filter(function(button){ return button.isWithinBounds(pos.x, pos.y); });
    if(_executeButton && clickedButtons.length > 0 ){ // button clicked
      clickedButtons[0].onClick();
    }
    return (clickedButtons.length > 0 );
  };

  InputHandler.prototype._onMouseDown = function(evt){
    // no button clicked
    if(!self.InputHandler._catchButtonClick(evt, false)){
      if(evt.button === 0){ // left/main button
        // set flag for image moving
        self.InputHandler.leftMouseButtonDown = true;
      }
    }
  };

  InputHandler.prototype._onMouseUp = function(evt){
    if(evt.button === 0){ // left/main button
      self.InputHandler.leftMouseButtonDown = false;
    }
  };

  InputHandler.prototype._targetClick = function(evt){
    if(!self.InputHandler._catchButtonClick(evt) && self.targetSettingMode){
      var target = self.target || { x: 0, y: 0 }
        , rect = self.canvas.getBoundingClientRect()
        , clickPos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
      self.target = convertToImagePosition(clickPos);
      self.dirty = true;
    }
  };

  InputHandler.prototype._onMouseWheel = function(evt){
    if (!evt) evt = event;
    evt.preventDefault();
    if(evt.detail<0 || evt.wheelDelta>0){ // up -> smaller
      self.zoomOut();
    } else { // down -> larger
      self.zoomIn();
    }
  };

  InputHandler.prototype._onMouseMove = function(evt){
    var lastPos = self.InputHandler.mouseLastPos
      , rect = self.canvas.getBoundingClientRect()
      , newPos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    if(lastPos !== null && self.InputHandler.leftMouseButtonDown){
      var deltaX = newPos.x - lastPos.x
        , deltaY = newPos.y - lastPos.y;

      self.center.x -= deltaX / self.scale;
      self.center.y -= deltaY / self.scale;
      self.dirty = true;
    }
    self.InputHandler.mouseLastPos = newPos;
  };

  function convertToImagePosition(canvasPosition){
    var visiblePart = {
          x: self.center.x >= (self.canvas.width / self.scale / 2) ? self.center.x - self.canvas.width / self.scale / 2 : 0,
          y: self.center.y >= (self.canvas.height / self.scale / 2) ? self.center.y - self.canvas.height / self.scale / 2 : 0
      }
      , canvasImage = {
          x: (self.center.x >= (self.canvas.width / self.scale / 2)) ? 0 : self.canvas.width / 2 - self.center.x * self.scale,
          y: (self.center.y >= (self.canvas.height / self.scale / 2)) ? 0 : self.canvas.height / 2 - self.center.y * self.scale
      }
      , imagePosition = {};

    imagePosition.x =
            visiblePart.x // image offset
          + canvasPosition.x / self.scale // de-scaled canvas position
          - canvasImage.x / self.scale; // de-scaled canvas offset
    imagePosition.y =
            visiblePart.y // image offset
          + canvasPosition.y  / self.scale // de-scaled canvas position
          - canvasImage.y / self.scale; // de-scaled canvas offset

    return imagePosition;
  }

  window.ImageViewer = ImageViewer;
}(window));
<commit_msg>move translation calculation to seperate function<commit_after>(function (window) {
  "use strict";

  var self;

  function ImageViewer(canvasId, imageUrl, options){
    self = this;

    options = (typeof options === 'object') ? options : {};

    // canvas
    this.canvas = document.getElementById(canvasId);
    this.context = this.canvas.getContext("2d");

    // dirty state
    this.dirty = true;

    // image scale
    this.scale = 1;
    this.scaleStep = 0.1;

    // image center (scroll offset)
    this.center = { x: 0, y: 0 };

    // image
    this.image = new Image();
    this.image.addEventListener('load', this._onImageLoad, false);
    this.image.src = imageUrl;

    // buttons
    this.buttons = [];

    // add buttons
    var padding = 10
      , radius = 20
      , x = this.canvas.width - radius - padding
      , y = this.canvas.height - radius - padding;

    var plusButton = new Button(x, y - 50, radius, drawPlusIcon);
    plusButton.onClick = function(){ self.zoomIn(); };
    this.buttons.push(plusButton);

    var minusButton = new Button(x, y, radius, drawMinusIcon);
    minusButton.onClick = function(){ self.zoomOut(); };
    this.buttons.push(minusButton);

    // setup target feature
    this.targetFeatureEnabled = (typeof options.target === 'boolean') ? options.target : false;
    this.targetSettingMode = false;
    this.target = null;
    this.targetButtons = [];

    // add target button
    var addTargetButton = new Button(x, y - 150, radius, drawTargetIcon);
    // onclick: toggle targetSettingMode
    addTargetButton.onClick = function(){
      addTargetButton.enabled = self.targetSettingMode = !self.targetSettingMode;
      self.dirty = true;
    };
    this.targetButtons.push(addTargetButton);

    // delete target button
    var deleteTargetButton = new Button(x, y - 100, radius, drawCrossIcon);
    deleteTargetButton.onClick = function(){
      self.target = null;
      self.dirty = true;
    };
    this.targetButtons.push(deleteTargetButton);

    // if target feature was enabled in the options, start it
    if(this.targetFeatureEnabled) this.enableTargetMode();

    // render loop
    this.FPS = 1000/30;
    this.tickInterval = null;

    this.InputHandler = new InputHandler(this.canvas, this);
  }

  ImageViewer.prototype._onImageLoad = function(){
    // set scale to use as much space inside the canvas as possible
    if(((self.canvas.height / self.image.height) * self.image.width) <= self.canvas.width){
      self.scale = self.canvas.height / self.image.height;
    } else {
      self.scale = self.canvas.width / self.image.width;
    }

    // center at image center
    self.center.x = self.image.width / 2;
    self.center.y = self.image.height / 2;

    // image changed
    self.dirty = true;

    // stop old render loop (if existed)
    if(self.tickInterval) clearInterval(self.tickInterval);

    // start new render loop
    self.tickInterval = setInterval(function(){ self._render(); }, self.FPS);
  };

  ImageViewer.prototype._render = function(){
    // check if dirty
    if(!this.dirty) return;
    this.dirty = false;

    var ctx = this.context;
    // clear canvas
    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

    // draw image (transformed and scaled)
    ctx.save();
    var translateX = this.canvas.width / 2 - this.center.x * this.scale
      , translateY = this.canvas.height / 2 - this.center.y * this.scale;

    ctx.translate(translateX, translateY);
    ctx.scale(this.scale, this.scale);

    ctx.drawImage(this.image, 0,0);

    ctx.restore();

    // draw buttons
    this.buttons.forEach(function(button){
      button.draw(ctx);
    });

    // draw target
    if(this.target !== null){
      this._drawTarget();
    }
  };

  ImageViewer.prototype.enableTargetMode = function(){
    this.buttons = this.buttons.concat(this.targetButtons);
    this.targetFeatureEnabled = true;
    this.dirty = true;
  };

  ImageViewer.prototype.disableTargetMode = function(){
    this.buttons = this.buttons.filter(function(b){ return self.targetButtons.indexOf(b) < 0; });
    this.targetFeatureEnabled = false;
    this.targetSettingMode = false;
    this.target = null;
    this.dirty = true;
  };

  ImageViewer.prototype._drawTarget = function(){
    var ctx = this.context;

    ctx.save();

    var shapeScale = 1.5
      , transalation = convertToCanvasTranslation(this.target);

    ctx.translate(transalation.x, transalation.y);
    ctx.scale(shapeScale * this.scale, shapeScale * this.scale);
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#ff0000';
    ctx.fillStyle = '#ff0000';

    // flag
    ctx.beginPath();
    ctx.moveTo(0, -20);
    ctx.lineTo(15, -15);
    ctx.lineTo(15, -25);
    ctx.lineTo(0, -30);
    ctx.lineTo(0, 0);
    ctx.stroke();

    // bulls-eye
    // inner circle
    ctx.beginPath();
    ctx.arc(0, 0, 5, 0, 2 * Math.PI, false);
    ctx.stroke();
    // outer circle
    ctx.beginPath();
    ctx.arc(0, 0, 10, 0, 2 * Math.PI, false);
    ctx.stroke();

    ctx.restore();
  };

  ImageViewer.prototype.zoomIn = function(){
    this.scale = this.scale * (1 + this.scaleStep);
    this.dirty = true;
  };

  ImageViewer.prototype.zoomOut = function(){
    this.scale = this.scale * (1 - this.scaleStep);
    this.dirty = true;
  };

  function Button(x, y, radius, icon){
    // centre coordinates
    this.x = x;
    this.y = y;

    // radius
    this.radius = radius;

    // transparency
    this.alpha = 0.5;

    // color
    this.color = '#000000';

    // icon drawing function
    // (ctx, x, y, radius, icon, color, alpha)
    this.icon = icon;

    // enabled state
    this.enabled = false;
    this.enabledAlpha = 0.7;

    // click action
    this.onClick = function(){ alert('no click action set!'); };
  }

  Button.prototype.isWithinBounds = function(x, y){
    var dx = Math.abs(this.x - x)
      , dy = Math.abs(this.y - y);
    return  dx * dx + dy * dy <= this.radius * this.radius;
  };

  Button.prototype.draw = function(ctx){
    // preserve context
    ctx.save();

    // drawing settings
    ctx.globalAlpha = (this.enabled) ? this.enabledAlpha : this.alpha;
    ctx.fillStyle= this.color;
    ctx.lineWidth = 0;

    // draw circle
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fill();

    // draw icon
    ctx.save();
    ctx.globalCompositeOperation = 'destination-out';
    this.icon(ctx, this.x, this.y, this.radius);
    ctx.restore();

    // restore context
    ctx.restore();
  };

  function drawMinusIcon(ctx, centerX, centerY, buttonRadius){
    var rectLength = buttonRadius
      , rectThickness = rectLength / 4
      , x = centerX - rectLength / 2
      , y = centerY - rectThickness / 2;

    ctx.fillRect(x, y, rectLength, rectThickness);
  }

  function drawPlusIcon(ctx, centerX, centerY, buttonRadius){
    /*
        11---10
        |     |
    01--12    09--08
    |              |
    02--03    06--07
        |     |
        04---05
    */
    var rectLength = buttonRadius
      , rectThickness = rectLength / 4;

    ctx.beginPath();
    // 1
    ctx.moveTo(centerX - rectLength / 2,
               centerY - rectThickness / 2);
    // 2
    ctx.lineTo(centerX - rectLength / 2,
               centerY + rectThickness / 2);
    // 3
    ctx.lineTo(centerX - rectThickness / 2,
               centerY + rectThickness / 2);
    // 4
    ctx.lineTo(centerX - rectThickness / 2,
               centerY + rectLength / 2);
    // 5
    ctx.lineTo(centerX + rectThickness / 2,
               centerY + rectLength / 2);
    // 6
    ctx.lineTo(centerX + rectThickness / 2,
               centerY + rectThickness / 2);
    // 7
    ctx.lineTo(centerX + rectLength / 2,
               centerY + rectThickness / 2);
    // 8
    ctx.lineTo(centerX + rectLength / 2,
               centerY - rectThickness / 2);
    // 9
    ctx.lineTo(centerX + rectThickness / 2,
               centerY - rectThickness / 2);
    // 10
    ctx.lineTo(centerX + rectThickness / 2,
               centerY - rectLength / 2);
    // 11
    ctx.lineTo(centerX - rectThickness / 2,
               centerY - rectLength / 2);
    // 12
    ctx.lineTo(centerX - rectThickness / 2,
               centerY - rectThickness / 2);

    ctx.closePath();
    ctx.fill();
  }

  function drawTargetIcon(ctx, centerX, centerY, buttonRadius){
    ctx.lineWidth = buttonRadius * 0.3;
    ctx.strokeStyle = self.color;
    ctx.beginPath();
    ctx.arc(centerX, centerY, buttonRadius * 0.5, 0, 2 * Math.PI);
    ctx.stroke();
  }

  function drawCrossIcon(ctx, centerX, centerY, buttonRadius){
    ctx.save();
      ctx.translate(centerX, centerY + buttonRadius * 0.7);
      ctx.save();
        ctx.rotate(Math.PI / 4);
        drawPlusIcon(ctx, - buttonRadius / 2, - buttonRadius / 2, buttonRadius);
      ctx.restore();
    ctx.restore();
  }

  function InputHandler(canvas, imageViewer) {
    this.canvas = canvas;
    this.imageViewer = imageViewer;

    // global
    this.leftMouseButtonDown = false;
    document.addEventListener('mousedown', this._onMouseDown);
    document.addEventListener('mouseup', this._onMouseUp);

    // zooming
    this.canvas.addEventListener('DOMMouseScroll', this._onMouseWheel);
    this.canvas.addEventListener('mousewheel', this._onMouseWheel);

    // moving
    this.mouseLastPos = null;
    this.canvas.addEventListener('mousemove', this._onMouseMove);

    // set target
    this.canvas.addEventListener('click', this._targetClick);
  }

  InputHandler.prototype._catchButtonClick = function(evt, executeButton){
    var _executeButton = (executeButton === false) ? false : true;
    // check if a button was clicked
    var rect = self.canvas.getBoundingClientRect()
      , pos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    var clickedButtons = self.buttons.filter(function(button){ return button.isWithinBounds(pos.x, pos.y); });
    if(_executeButton && clickedButtons.length > 0 ){ // button clicked
      clickedButtons[0].onClick();
    }
    return (clickedButtons.length > 0 );
  };

  InputHandler.prototype._onMouseDown = function(evt){
    // no button clicked
    if(!self.InputHandler._catchButtonClick(evt, false)){
      if(evt.button === 0){ // left/main button
        // set flag for image moving
        self.InputHandler.leftMouseButtonDown = true;
      }
    }
  };

  InputHandler.prototype._onMouseUp = function(evt){
    if(evt.button === 0){ // left/main button
      self.InputHandler.leftMouseButtonDown = false;
    }
  };

  InputHandler.prototype._targetClick = function(evt){
    if(!self.InputHandler._catchButtonClick(evt) && self.targetSettingMode){
      var target = self.target || { x: 0, y: 0 }
        , rect = self.canvas.getBoundingClientRect()
        , clickPos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
      self.target = convertToImagePosition(clickPos);
      self.dirty = true;
    }
  };

  InputHandler.prototype._onMouseWheel = function(evt){
    if (!evt) evt = event;
    evt.preventDefault();
    if(evt.detail<0 || evt.wheelDelta>0){ // up -> smaller
      self.zoomOut();
    } else { // down -> larger
      self.zoomIn();
    }
  };

  InputHandler.prototype._onMouseMove = function(evt){
    var lastPos = self.InputHandler.mouseLastPos
      , rect = self.canvas.getBoundingClientRect()
      , newPos = {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    if(lastPos !== null && self.InputHandler.leftMouseButtonDown){
      var deltaX = newPos.x - lastPos.x
        , deltaY = newPos.y - lastPos.y;

      self.center.x -= deltaX / self.scale;
      self.center.y -= deltaY / self.scale;
      self.dirty = true;
    }
    self.InputHandler.mouseLastPos = newPos;
  };

  function convertToImagePosition(canvasPosition){
    var visiblePart = {
          x: self.center.x >= (self.canvas.width / self.scale / 2) ? self.center.x - self.canvas.width / self.scale / 2 : 0,
          y: self.center.y >= (self.canvas.height / self.scale / 2) ? self.center.y - self.canvas.height / self.scale / 2 : 0
      }
      , canvasImage = {
          x: (self.center.x >= (self.canvas.width / self.scale / 2)) ? 0 : self.canvas.width / 2 - self.center.x * self.scale,
          y: (self.center.y >= (self.canvas.height / self.scale / 2)) ? 0 : self.canvas.height / 2 - self.center.y * self.scale
      }
      , imagePosition = {};

    imagePosition.x =
            visiblePart.x // image offset
          + canvasPosition.x / self.scale // de-scaled canvas position
          - canvasImage.x / self.scale; // de-scaled canvas offset
    imagePosition.y =
            visiblePart.y // image offset
          + canvasPosition.y  / self.scale // de-scaled canvas position
          - canvasImage.y / self.scale; // de-scaled canvas offset

    return imagePosition;
  }

  function convertToCanvasTranslation(imagePosition){
    return {
      x: (
            imagePosition.x  // x-position on picture
          + self.canvas.width / self.scale / 2 // offset of scaled canvas
          - self.center.x // scroll offset of image
         ) * self.scale, // scale the transformation

      y: (
            imagePosition.y  // y-position on picture
          + self.canvas.height / self.scale / 2 // offset of scaled canvas
          - self.center.y // scroll offset of image
         ) * self.scale // scale the transformation
    };
  }

  window.ImageViewer = ImageViewer;
}(window));
<|endoftext|>