<commit_before>'use strict';

angular.module('polls').controller('PollsSearchController', [
  '$location',
  '$scope',
  '$state',
  'Authentication',
  'CategorysService',
  'Action',
  '$stateParams',
  'Storages',
  'Constants',
  'toastr',
  'ngDialog',
  'Profile',
  function ($location, $scope, $state, Authentication, Categorys, Action, $stateParams, Storages, Constants, toast, dialog, Profile) {
    $scope.user = Authentication.user;
    $scope.isLogged = ($scope.user) ? true : false;
    $scope.detailToggle = -1;
    $scope.form = {};
    $scope.categorys = Categorys.query();

    $scope.condition = {};
    $scope.condition.key = $stateParams.key;
    $scope.condition.in = $stateParams.in;
    $scope.condition.status = $stateParams.status;
    $scope.condition.ctgr = $stateParams.ctgr;

    $scope.condition.cmt = $stateParams.cmt;
    $scope.condition.compare = $stateParams.compare;

    $scope.condition.created = $stateParams.created;
    $scope.condition.timing = $stateParams.timing;

    $scope.condition.sort = $stateParams.sort;
    $scope.condition.sortkind = $stateParams.sortkind;

    $scope.condition.by = $stateParams.by;
    if ($scope.condition.by) {
      Profile.get({ userId: $scope.condition.by }, _user => {
        $scope.selectedUser = _user;
      });
    }
    $scope.search = () => {
      $state.go('search', $scope.condition);
    };

    $scope.busy = false;
    $scope.polls = [];
    $scope.sort = '-poll.created';
    excute();
    function excute() {
      if (check_params()) {
        $scope.busy = true;
        Action.search($scope.condition)
          .then(res => {
            $scope.polls = res.data;
            var promise = [];
            $scope.polls.forEach(function (item) {
              promise.push(get_owner_follow(item.poll));
              promise.push(get_reported(item.poll));
              promise.push(get_bookmarked(item.poll));
            }, this);
            return Promise.all(promise);
          })
          .then(res => {
            create_sort();
            $scope.busy = false;
          })
          .catch(err => {
            $scope.busy = false;
            console.log(err);
          });
      } else {
        $scope.condition = JSON.parse(Storages.get_local(Constants.storages.preferences, JSON.stringify({})));
      }
    }
    function check_params() {
      if ($scope.condition.key || $scope.condition.status || $scope.condition.by || $scope.condition.ctgr || $scope.condition.cmt || $scope.condition.created) {
        return true;
      }
      return false;
    }
    function create_sort() {
      if ($scope.condition.sort) {
        var prefix = ($scope.condition.sort === 'created') ? 'poll.' : 'report.';
        var kind = ($scope.condition.sortkind === 'desc') ? '-' : '';
        $scope.sort = kind + prefix + $scope.condition.sort;
      }
    }

    function get_owner_follow(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.follow = {};
          return resolve();
        }
        Action.get_follow(poll._id)
          .then(res => {
            poll.follow = res.data || { poll: poll._id };
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_reported(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.reported = false;
          return resolve();
        }
        Action.get_report(poll._id)
          .then(res => {
            poll.reported = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_bookmarked(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.bookmarked = false;
          return resolve();
        }
        Action.get_bookmark(poll._id)
          .then(res => {
            poll.bookmarked = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    $scope.selectedUserFn = function (selected) {
      if (selected) {
        $scope.condition.by = selected.originalObject._id;
        $scope.selectedUser = selected.originalObject;
      } else {
        $scope.condition.by = undefined;
        $scope.selectedUser = undefined;
      }
    };
    $scope.clear_preferences = () => {
      $scope.condition = {};
      $scope.selectedUser = undefined;
      Storages.set_local(Constants.storages.preferences, JSON.stringify($scope.condition));
      // $location.url($location.path());
      $state.go('search', {}, { notify: false })
    };
    $scope.save_preferences = () => {
      Storages.set_local(Constants.storages.preferences, JSON.stringify($scope.condition));
    };
    $scope.delete_poll = (poll) => {
      if (poll.user._id !== $scope.user._id) {
        toast.error('You are not authorized.', 'Error!');
        return;
      }
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete this poll?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        $scope.polls = _.reject($scope.polls, function (item) {
          return item.poll._id === poll._id;
        });
        // Action.delete_poll(poll);
      }
    };
    $scope.report_poll = (poll) => {
      if (poll.reported) {
        toast.error('You are already reported ' + poll.title, 'Error!');
        return;
      }
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/report.dialog.template.html'
      }).then(reason => {
        handle_confirm(reason);
      }, reject => {
      });
      function handle_confirm(reason) {
        Action.save_report(poll._id, reason)
          .then(res => {
            poll.reported = (res) ? true : false;
            toast.success('You have successfully reported ' + poll.title, 'Thank you!');
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };
    $scope.bookmark_poll = (poll) => {
      if (poll.bookmarked) {
        toast.error('You are already bookmark ' + poll.title, 'Error!');
        return;
      }
      Action.save_bookmark(poll._id)
        .then(res => {
          poll.bookmarked = (res) ? true : false;
          toast.success('Added ' + poll.title + ' to bookmarks.', 'Success!');
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.follow_poll = (poll) => {
      if (!$scope.isLogged) {
        toast.error('You must login to follow poll.', 'Error!');
        return;
      }
      Action.save_follow(poll.follow)
        .then(res => {
          poll.follow = res;
          if (poll.follow.following) {
            toast.success('You followed ' + poll.title, 'Success!');
          }
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
  }
]);
<commit_msg>Commited from lenh at Fri, Jul 21, 2017  4:47:27 PM<commit_after>'use strict';

angular.module('polls').controller('PollsSearchController', [
  '$location',
  '$scope',
  '$state',
  'Authentication',
  'CategorysService',
  'Action',
  '$stateParams',
  'Storages',
  'Constants',
  'toastr',
  'ngDialog',
  'Profile',
  function ($location, $scope, $state, Authentication, Categorys, Action, $stateParams, Storages, Constants, toast, dialog, Profile) {
    $scope.user = Authentication.user;
    $scope.isLogged = ($scope.user) ? true : false;
    $scope.detailToggle = -1;
    $scope.form = {};
    $scope.categorys = Categorys.query();

    $scope.condition = {};
    $scope.condition.key = $stateParams.key;
    $scope.condition.in = $stateParams.in;
    $scope.condition.status = $stateParams.status;
    $scope.condition.ctgr = $stateParams.ctgr;

    $scope.condition.cmt = $stateParams.cmt;
    $scope.condition.compare = $stateParams.compare;

    $scope.condition.created = $stateParams.created;
    $scope.condition.timing = $stateParams.timing;

    $scope.condition.sort = $stateParams.sort;
    $scope.condition.sortkind = $stateParams.sortkind;

    $scope.condition.by = $stateParams.by;
    if ($scope.condition.by) {
      Profile.get({ userId: $scope.condition.by }, _user => {
        $scope.selectedUser = _user;
      });
    }
    $scope.search = () => {
      $state.go('search', $scope.condition);
    };

    $scope.busy = false;
    $scope.polls = [];
    $scope.sort = '-poll.created';
    excute();
    function excute() {
      if (check_params()) {
        $scope.busy = true;
        Action.search($scope.condition)
          .then(res => {
            $scope.polls = res.data;
            var promise = [];
            $scope.polls.forEach(function (item) {
              promise.push(get_owner_follow(item.poll));
              promise.push(get_reported(item.poll));
              promise.push(get_bookmarked(item.poll));
            }, this);
            return Promise.all(promise);
          })
          .then(res => {
            create_sort();
            $scope.busy = false;
          })
          .catch(err => {
            $scope.busy = false;
            console.log(err);
          });
      } else {
        $scope.condition = JSON.parse(Storages.get_local(Constants.storages.preferences, JSON.stringify({})));
      }
    }
    function check_params() {
      if ($scope.condition.key || $scope.condition.status || $scope.condition.by || $scope.condition.ctgr || $scope.condition.cmt || $scope.condition.created) {
        return true;
      }
      return false;
    }
    function create_sort() {
      if ($scope.condition.sort) {
        var prefix = ($scope.condition.sort === 'created') ? 'poll.' : 'report.';
        var kind = ($scope.condition.sortkind === 'desc') ? '-' : '';
        $scope.sort = kind + prefix + $scope.condition.sort;
      }
    }

    function get_owner_follow(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.follow = {};
          return resolve();
        }
        Action.get_follow(poll._id)
          .then(res => {
            poll.follow = res.data || { poll: poll._id };
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_reported(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.reported = false;
          return resolve();
        }
        Action.get_report(poll._id)
          .then(res => {
            poll.reported = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_bookmarked(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.bookmarked = false;
          return resolve();
        }
        Action.get_bookmark(poll._id)
          .then(res => {
            poll.bookmarked = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    $scope.selectedUserFn = function (selected) {
      if (selected) {
        $scope.condition.by = selected.originalObject._id;
        $scope.selectedUser = selected.originalObject;
      } else {
        $scope.condition.by = undefined;
        $scope.selectedUser = undefined;
      }
    };
    $scope.clear_preferences = () => {
      $scope.condition = {};
      $scope.selectedUser = undefined;
      Storages.set_local(Constants.storages.preferences, JSON.stringify($scope.condition));
      // $location.url($location.path());
      $state.go('search', {}, { notify: false });
    };
    $scope.save_preferences = () => {
      Storages.set_local(Constants.storages.preferences, JSON.stringify($scope.condition));
    };
    $scope.delete_poll = (poll) => {
      if (poll.user._id !== $scope.user._id) {
        toast.error('You are not authorized.', 'Error!');
        return;
      }
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete this poll?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        $scope.polls = _.reject($scope.polls, function (item) {
          return item.poll._id === poll._id;
        });
        // Action.delete_poll(poll);
      }
    };
    $scope.report_poll = (poll) => {
      if (poll.reported) {
        toast.error('You are already reported ' + poll.title, 'Error!');
        return;
      }
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/report.dialog.template.html'
      }).then(reason => {
        handle_confirm(reason);
      }, reject => {
      });
      function handle_confirm(reason) {
        Action.save_report(poll._id, reason)
          .then(res => {
            poll.reported = (res) ? true : false;
            toast.success('You have successfully reported ' + poll.title, 'Thank you!');
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };
    $scope.bookmark_poll = (poll) => {
      if (poll.bookmarked) {
        toast.error('You are already bookmark ' + poll.title, 'Error!');
        return;
      }
      Action.save_bookmark(poll._id)
        .then(res => {
          poll.bookmarked = (res) ? true : false;
          toast.success('Added ' + poll.title + ' to bookmarks.', 'Success!');
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.follow_poll = (poll) => {
      if (!$scope.isLogged) {
        toast.error('You must login to follow poll.', 'Error!');
        return;
      }
      Action.save_follow(poll.follow)
        .then(res => {
          poll.follow = res;
          if (poll.follow.following) {
            toast.success('You followed ' + poll.title, 'Success!');
          }
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
  }
]);
<|endoftext|>


<commit_before>const {addHandler, handle} = require('./event');

addHandler('load', (state) => {
    window.addEventListener('focus', () => handle(state, 'windowfocus'));
    window.addEventListener('blur', () => handle(state, 'windowblur'));
    window.addEventListener('resize', event => handle(state, 'resize'));

    document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
            handle(state, 'pagehide');
        } else {
            handle(state, 'pageshow');
        }
    });
});

function mouseXY(event, component) {
    const x = event.pageX - (component.offsetLeft || 0);
    const y = event.pageY - (component.offsetTop || 0);
    return {x, y};
}

export function startMouseEvent(state, name, component) {
    component.addEventListener(name, (event) => {
        handle(state, name, mouseXY(event, component));
    });
}

window.addEventListener('drop', ((event) => event.preventDefault()), true);
window.addEventListener('dragover', ((event) => event.preventDefault()), true);
<commit_msg>Workaround for mouse event contention across components<commit_after>const {addHandler, handle} = require('./event');

addHandler('load', (state) => {
    window.addEventListener('focus', () => handle(state, 'windowfocus'));
    window.addEventListener('blur', () => handle(state, 'windowblur'));
    window.addEventListener('resize', event => handle(state, 'resize'));

    document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
            handle(state, 'pagehide');
        } else {
            handle(state, 'pageshow');
        }
    });
});

function mouseXY(event, component) {
    const x = event.pageX - (component.offsetLeft || 0);
    const y = event.pageY - (component.offsetTop || 0);
    return {x, y};
}

export function startMouseEvent(state, name, component, skidEventName=name) {
    component.addEventListener(name, (event) => {
        handle(state, skidEventName, mouseXY(event, component));
    });
}

window.addEventListener('drop', ((event) => event.preventDefault()), true);
window.addEventListener('dragover', ((event) => event.preventDefault()), true);
<|endoftext|>


<commit_before>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    https://github.com/gocom/dense
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

;(function (factory)
{
	if (typeof define === 'function' && define.amd)
	{
		define(['jquery'], factory);
	}
	else
	{
		factory(jQuery);
	}
}(function ($)
{
    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * An array of accepted content-types.
     *
     * Basically contains an array of raster image formats.
     */

    acceptedTypes =
    [
        'image/jpg',
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/bmp'
    ],

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Renders a pixel-ratio-aware image.
     *
     * Dense defaults to the init method if no
     * method is specified.
     *
     * The method should be used to select the images that
     * should display retina-size images on high pixel ratio
     * devices.
     *
     * The correct image variation is selected based on the
     * device's pixel ratio. If the image element defines
     * data-{ratio}x (e.g. data-1x, data-2x, data-3x) attributes,
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the specified src attribute.
     * The searched high pixel ratio images follow
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request. The check makes sure no
     * HTTP error code is returned, and that the received content-type
     * is either image/jpg, image/png,
     * image/gif or image/bmp. Vector image
     * formats, like svg, are skipped.
     *
     * This method can also be used to load image in semi-lazy fashion.
     * If the selector targets a element that isn't an image, an
     * image is appended to that location. The image is constructed
     * using the specified data-{ratio}x attributes like
     * with normal images.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           A prefix added to the generated links
     * @param    {String}  [options.dimensions=preserve] What to do with the width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img.retina').dense({
     *  'ping'      : false,
     *  'dimension' : true
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        return this.not('.dense-active').each(function ()
        {
            var $this = $(this),
                target,
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                ext;

            if (image)
            {
                if ($this.not('img'))
                {
                    target = $this.siblings('img.dense-active').eq(0);

                    if (!target.length)
                    {
                        target = $('');
                        $this.append(target);
                    }

                    $this = target;
                }
            }
            else
            {
                if (!originalImage || devicePixelRatio == 1)
                {
                    return;
                }

                ext = image.split('.').pop().split(/[\?\#]/).shift();

                if ($.inArray(ext, skipExtensions))
                {
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (regexProtocol.test(image) === false || image.indexOf('://' + document.domain) !== -1);
            }

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                       var type = jqXHR.getResponseHeader('Content-type').split(';').shift();

                       if (jqXHR.status === 200 && (type === null || $.inArray(type, acceptedTypes) !== -1))
                       {
                           pathStack.push(image);

                           $this
                               .attr('src', image)
                               .data('dense-original', originalImage);

                            if (options.dimensions === 'update')
                            {
                                methods.updateDimensions.call($this.get(0));
                            }

                            $this.trigger('dense-retina-loaded');
                       }
                    });
            }
            else
            {
                $this
                    .attr('src', image)
                    .data('dense-original', originalImage);

                if (options.dimensions === 'update')
                {
                    methods.updateDimensions.call($this.get(0));
                }

                $this.trigger('dense-retina-loaded');
            }

            if (options.dimensions === 'remove')
            {
                $this.removeAttr('width').removeAttr('height');
            }
        }).addClass('dense-active');
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values.
     *
     * This method is asynchronous, so you can not directly return
     * its values. Instead use load event.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr('width', img.width).attr('height', img.height);
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(min--moz-device-pixel-ratio: '+ratio+')',
                    '(-o-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    pixelRatio = ratio;
                    return false;
                }
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes.
     *
     * If the devices pixel ratio is greater than the largest specified image,
     * the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $(this).attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * Is invoked when an retina image has finished loading.
     *
     * This event does not take into account dimension updates
     * which are run asynchronously after the retina image has
     * been loaded.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */
}));<commit_msg>getImageAttribute uses the first image.<commit_after>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    https://github.com/gocom/dense
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

;(function (factory)
{
	if (typeof define === 'function' && define.amd)
	{
		define(['jquery'], factory);
	}
	else
	{
		factory(jQuery);
	}
}(function ($)
{
    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * An array of accepted content-types.
     *
     * Basically contains an array of raster image formats.
     */

    acceptedTypes =
    [
        'image/jpg',
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/bmp'
    ],

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Renders a pixel-ratio-aware image.
     *
     * Dense defaults to the init method if no
     * method is specified.
     *
     * The method should be used to select the images that
     * should display retina-size images on high pixel ratio
     * devices.
     *
     * The correct image variation is selected based on the
     * device's pixel ratio. If the image element defines
     * data-{ratio}x (e.g. data-1x, data-2x, data-3x) attributes,
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the specified src attribute.
     * The searched high pixel ratio images follow
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request. The check makes sure no
     * HTTP error code is returned, and that the received content-type
     * is either image/jpg, image/png,
     * image/gif or image/bmp. Vector image
     * formats, like svg, are skipped.
     *
     * This method can also be used to load image in semi-lazy fashion.
     * If the selector targets a element that isn't an image, an
     * image is appended to that location. The image is constructed
     * using the specified data-{ratio}x attributes like
     * with normal images.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           A prefix added to the generated links
     * @param    {String}  [options.dimensions=preserve] What to do with the width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img.retina').dense({
     *  'ping'      : false,
     *  'dimension' : true
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        return this.not('.dense-active').each(function ()
        {
            var $this = $(this),
                target,
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                ext;

            if (image)
            {
                if ($this.not('img'))
                {
                    target = $this.siblings('img.dense-active').eq(0);

                    if (!target.length)
                    {
                        target = $('');
                        $this.append(target);
                    }

                    $this = target;
                }
            }
            else
            {
                if (!originalImage || devicePixelRatio == 1)
                {
                    return;
                }

                ext = image.split('.').pop().split(/[\?\#]/).shift();

                if ($.inArray(ext, skipExtensions))
                {
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (regexProtocol.test(image) === false || image.indexOf('://' + document.domain) !== -1);
            }

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                       var type = jqXHR.getResponseHeader('Content-type').split(';').shift();

                       if (jqXHR.status === 200 && (type === null || $.inArray(type, acceptedTypes) !== -1))
                       {
                           pathStack.push(image);

                           $this
                               .attr('src', image)
                               .data('dense-original', originalImage);

                            if (options.dimensions === 'update')
                            {
                                methods.updateDimensions.call($this.get(0));
                            }

                            $this.trigger('dense-retina-loaded');
                       }
                    });
            }
            else
            {
                $this
                    .attr('src', image)
                    .data('dense-original', originalImage);

                if (options.dimensions === 'update')
                {
                    methods.updateDimensions.call($this.get(0));
                }

                $this.trigger('dense-retina-loaded');
            }

            if (options.dimensions === 'remove')
            {
                $this.removeAttr('width').removeAttr('height');
            }
        }).addClass('dense-active');
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values.
     *
     * This method is asynchronous, so you can not directly return
     * its values. Instead use load event.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr('width', img.width).attr('height', img.height);
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(min--moz-device-pixel-ratio: '+ratio+')',
                    '(-o-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    pixelRatio = ratio;
                    return false;
                }
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes.
     *
     * If the devices pixel ratio is greater than the largest specified image,
     * the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $this.attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * Is invoked when an retina image has finished loading.
     *
     * This event does not take into account dimension updates
     * which are run asynchronously after the retina image has
     * been loaded.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */
}));<|endoftext|>


<commit_before>#!/usr/bin/env node

const Config = require('./cli/config').createConfigWith('config.json')

if (!Config.isSet()) {
  require('./commands/config')
} else {
  require('./commands/actions')
}
<commit_msg>added harmony to support backward compatability<commit_after>#!/usr/bin/env node --harmony

const Config = require('./cli/config').createConfigWith('config.json')

if (!Config.isSet()) {
  require('./commands/config')
} else {
  require('./commands/actions')
}
<|endoftext|>


<commit_before>'use strict';

var $        = require('jquery'),
    jqToggle = require('toggles'),
    Snap     = require('Snap'),
    pageManager = require('./pages');

var snap,
    questManager;

function init(options) {
    questManager = options.questManager;
    // Need these to not allow overscrolling
    $(window).bind('touchmove', function (e) {
        e.preventDefault();
    });
    $('body').on('touchmove','.scrollable', function (e) {
        e.stopPropagation();
    });

    initSnap();
    initToggleButtons();

    $('.menu-link').on('click', toggleMenu);
    $('.menu').on('click', 'a', togglePages);
}

function initToggleButtons() {
    $('.toggles').toggles({
        height: 35,
        width: 100,
        on: false
    });
}

function initSnap() {
    snap = new Snap({
        element: document.getElementById('content'),
        dragger: null,
        disable: 'right',
        addBodyClasses: true,
        hyperextensible: false,
        resistance: 0.5,
        flickThreshold: 50,
        transitionSpeed: 0.3,
        easing: 'ease',
        maxPosition: 266,
        minPosition: -266,
        tapToClose: true,
        touchToDrag: false,
        slideIntent: 40,
        minDragDistance: 5
    });
}

function toggleMenu() {
    if (snap.state().state === 'left' ) {
        snap.close();
    } else {
        snap.open('left');
    }
}

function togglePages(e) {
    e.preventDefault();
    var page = $(e.currentTarget).data('page');
    var target = $(e.currentTarget).attr('data-page');
    var activePage = $('#content').find('.page.active').attr('id');

    if (activePage !== target) {
        pageManager.crossFade($('#' + activePage), $('#' + target));
        snap.close();
        pageManager.loadPage(target, $('#' + target), questManager);
    }
}

module.exports = {
    init: init
};
<commit_msg>Close menu if selected page is already active.<commit_after>'use strict';

var $        = require('jquery'),
    jqToggle = require('toggles'),
    Snap     = require('Snap'),
    pageManager = require('./pages');

var snap,
    questManager;

function init(options) {
    questManager = options.questManager;
    // Need these to not allow overscrolling
    $(window).bind('touchmove', function (e) {
        e.preventDefault();
    });
    $('body').on('touchmove','.scrollable', function (e) {
        e.stopPropagation();
    });

    initSnap();
    initToggleButtons();

    $('.menu-link').on('click', toggleMenu);
    $('.menu').on('click', 'a', togglePages);
}

function initToggleButtons() {
    $('.toggles').toggles({
        height: 35,
        width: 100,
        on: false
    });
}

function initSnap() {
    snap = new Snap({
        element: document.getElementById('content'),
        dragger: null,
        disable: 'right',
        addBodyClasses: true,
        hyperextensible: false,
        resistance: 0.5,
        flickThreshold: 50,
        transitionSpeed: 0.3,
        easing: 'ease',
        maxPosition: 266,
        minPosition: -266,
        tapToClose: true,
        touchToDrag: false,
        slideIntent: 40,
        minDragDistance: 5
    });
}

function toggleMenu() {
    if (snap.state().state === 'left' ) {
        snap.close();
    } else {
        snap.open('left');
    }
}

function togglePages(e) {
    e.preventDefault();
    var page = $(e.currentTarget).data('page');
    var target = $(e.currentTarget).attr('data-page');
    var activePage = $('#content').find('.page.active').attr('id');

    if (activePage !== target) {
        pageManager.crossFade($('#' + activePage), $('#' + target));
        snap.close();
        pageManager.loadPage(target, $('#' + target), questManager);
    } else {
        toggleMenu();
    }
}

module.exports = {
    init: init
};
<|endoftext|>


<commit_before>'use strict';

var ui = function() {
    return {
        progress: function(percents) {
            var resultBar = $('div.search-result-bar');
            if (resultBar.length === 0) {
                return false;
            }

            var progressBar = resultBar.find('.progress-bar');
            if (progressBar.length === 0) {
                return false;
            }

            if (percents === 100) {
                resultBar.removeClass('progress-mode');

                progressBar.width(0);
            } else {
                resultBar.addClass('progress-mode');

                progressBar.width(percents + '%');
            }

            return true;
        },
        notFound: function() {
            var modal = $('#emptyModal');
            if (modal.length === 0) {
                return false;
            }

            modal.modal();

            return true;
        },
        enableModes: function() {
            var buttons = $('div.search-result-bar label.btn');
            if (buttons.length === 0) {
                return false;
            }

            buttons.removeClass('disabled');

            return true;
        },
        searchOn: function() {
            var button = $('.search-button button');
            if (button.length === 0) {
                return false;
            }

            button.removeAttr('disabled');

            return true;
        },
        searchOff: function() {
            var button = $('.search-button button#startButton');
            if (button.length === 0) {
                return false;
            }

            button.attr('disabled', 'disabled');

            return true;
        },
        clean: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.removeClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text('');

            return true;
        },
        correct: function($input, name) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.addClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text(name);

            return true;
        },
        incorrect: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.addClass('has-error');
            container.removeClass('has-success');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-remove');
            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text('');

            return true;
        },
        lookForUser: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.removeClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-refresh');
            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');

            return true;
        },
        panel: {
            changePanel: function(panelName) {
                var panel = $('div.result-panels div.result-panel#' + panelName);
                if (panel.length === 0) {
                    return false;
                }

                $('div.result-panels div.result-panel').removeClass('active');
                panel.addClass('active');

                return true;
            },
            count: function(data) {
                var count = data.sequences[0] ? (data.sequences[0].length - 2) : 'до хрена';

                var panel = $('div.result-panels div.result-panel#count');
                if (panel.length === 0) {
                    return false;
                }

                panel.empty();

                var zeroRow = $('
');
                zeroRow.addClass('empty-row');

                var firstRow = $('
');

                $.each(Array(count), function() {
                    var icon = $('');
                    icon.addClass('glyphicon glyphicon-user count-icon');

                    firstRow.append(icon);
                });

                var secondRow = $('
');

                var usersStr = String(count).slice(-1) === '1' ? 'пользователя' : 'пользователей';
                secondRow.append('Вы знакомы через ' + count + ' ' + usersStr + '');

                panel.append(zeroRow, firstRow, secondRow);

                return true;
            },
            write: function(data) {
                var group = $('div.result-panels div.result-panel ul.list-group');
                if (group.length === 0) {
                    return false;
                }

                group.find('li.list-group-item').remove();

                data.sequences.forEach(function(row) {
                    row = row.map(function(id) {
                        return data.users.filter(function(item) {
                            return item.uid === id
                        })[0];
                    });

                    var li = $('
');

                    var table = $('
');
                    li.append(table);

                    row.forEach(function(user) {
                        var title = 'title="
Пол: {1}

ДР: {2}

"'.format(
                            user.photo_100,
                            user.sex === 2 ? 'мужской' : user.sex === 1 ? 'женский' : 'не говорит',
                            user.bdate || 'не говорит'
                        );

                        var href = 'href="http://vk.com/id{0}"'.format(user.uid);

                        var cell = $('
');

                        cell.append('' + [user.first_name, user.last_name].join(' ') + '');
                        table.append(cell);
                    });

                    group.append(li);
                });

                group.find('[title]').tooltip({
                    html: true
                });

                return true;
            },
            draw: function(data) {
                var panel = $('div.result-panels div.result-panel#draw');
                if (panel.length === 0) {
                    return false;
                }

                panel.empty();

                var firstUser, secondUser;
                var sequence = data.sequences[0];
                if (sequence) {
                    firstUser = sequence[0];
                    secondUser = sequence[sequence.length - 1];
                }

                var pairs = [];

                data.sequences.forEach(function(item) {
                    item.reduce(function(a, b) {
                        pairs.push([a, b]);

                        return b;
                    });
                });

                pairs = pairs.filter(function(item, index) {
                    return pairs.filter(function(item1, index1) {
                        return index > index1 && (item[0] === item1[0] && item[1] === item1[1]);
                    }).length === 0;
                });

                var links = pairs.map(function(pair) {
                    return {
                        source: pair[0],
                        target: pair[1]
                    }
                });

                var nodes = {};

                links.forEach(function(link) {
                    var sourceUser = data.users.filter(function(item) {
                        return item.uid === link.source
                    })[0];

                    link.source = nodes[link.source] || (nodes[link.source] = {
                        name: link.source,
                        label: [sourceUser.first_name, sourceUser.last_name].join(' ')
                    });

                    var targetUser = data.users.filter(function(item) {
                        return item.uid === link.target
                    })[0];

                    link.target = nodes[link.target] || (nodes[link.target] = {
                        name: link.target,
                        label: [targetUser.first_name, targetUser.last_name].join(' ')
                    });
                });

                var width = panel.closest('.container').width(),
                    height = width * 0.5;

                var force = d3.layout.force()
                    .nodes(d3.values(nodes))
                    .links(links)
                    .size([width, height])
                    .linkDistance(150)
                    .charge(-100)
                    .on('tick', function() {
                        path.attr('d', function(d) {
                            return 'M' + d.source.x + ',' + d.source.y + ' ' + d.target.x + ',' + d.target.y;
                        });

                        circle.attr('transform', function(d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        });

                        text.attr('transform', function(d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        });
                    }).start();

                var svg = d3.select('div.result-panels div.result-panel#draw').append('svg')
                    .attr('width', width)
                    .attr('height', height);

                svg.append('defs').selectAll('marker')
                    .data([])
                    .enter().append('marker')
                    .attr('id', function(d) {
                        return d;
                    })
                    .attr('viewBox', '0 -5 10 10')
                    .attr('refX', 15)
                    .attr('refY', -1.5)
                    .attr('markerWidth', 8)
                    .attr('markerHeight', 8)
                    .attr('orient', 'auto')
                    .append('path')
                    .attr('d', 'M0,-5L10,0L0,5');

                var path = svg.append('g').selectAll('path')
                    .data(force.links())
                    .enter().append('path')
                    .attr('class', function(d) {
                        return 'link';
                    });

                var circle = svg.append('g').selectAll('circle')
                    .data(force.nodes())
                    .enter().append('circle')
                    .attr('r', 8)
                    .attr('class', function(d) {
                        if (d.name === firstUser || d.name === secondUser) return 'red';
                    })
                    .call(force.drag);

                var text = svg.append('g').selectAll('text')
                    .data(force.nodes())
                    .enter().append('text')
                    .attr('x', 12)
                    .attr('y', 3)
                    .text(function(d) {
                        return d.label;
                    });

                var container = panel.closest('.container');

                setInterval(function() {
                    width = container.width();
                    height = width * 0.5;

                    force.size([width, height]);

                    svg.attr('height', height);
                }, 2000);

                return true;
            }
        }
    }
}();<commit_msg>[Remove] message<commit_after>'use strict';

var ui = function() {
    return {
        progress: function(percents) {
            var resultBar = $('div.search-result-bar');
            if (resultBar.length === 0) {
                return false;
            }

            var progressBar = resultBar.find('.progress-bar');
            if (progressBar.length === 0) {
                return false;
            }

            if (percents === 100) {
                resultBar.removeClass('progress-mode');

                progressBar.width(0);
            } else {
                resultBar.addClass('progress-mode');

                progressBar.width(percents + '%');
            }

            return true;
        },
        notFound: function() {
            var modal = $('#emptyModal');
            if (modal.length === 0) {
                return false;
            }

            modal.modal();

            return true;
        },
        enableModes: function() {
            var buttons = $('div.search-result-bar label.btn');
            if (buttons.length === 0) {
                return false;
            }

            buttons.removeClass('disabled');

            return true;
        },
        searchOn: function() {
            var button = $('.search-button button');
            if (button.length === 0) {
                return false;
            }

            button.removeAttr('disabled');

            return true;
        },
        searchOff: function() {
            var button = $('.search-button button#startButton');
            if (button.length === 0) {
                return false;
            }

            button.attr('disabled', 'disabled');

            return true;
        },
        clean: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.removeClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text('');

            return true;
        },
        correct: function($input, name) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.addClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text(name);

            return true;
        },
        incorrect: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.addClass('has-error');
            container.removeClass('has-success');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-remove');
            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-refresh');

            var username = container.find('.feedback-user-name');
            if (username.length === 0) {
                return false;
            }

            username.text('');

            return true;
        },
        lookForUser: function($input) {
            var container = $input.closest('div.has-feedback');
            if (container.length === 0) {
                return false;
            }

            container.removeClass('has-success');
            container.removeClass('has-error');

            var icon = container.find('span.glyphicon');
            if (icon.length === 0) {
                return false;
            }

            icon.addClass('glyphicon-refresh');
            icon.removeClass('glyphicon-ok');
            icon.removeClass('glyphicon-remove');

            return true;
        },
        panel: {
            changePanel: function(panelName) {
                var panel = $('div.result-panels div.result-panel#' + panelName);
                if (panel.length === 0) {
                    return false;
                }

                $('div.result-panels div.result-panel').removeClass('active');
                panel.addClass('active');

                return true;
            },
            count: function(data) {
                var count = data.sequences[0].length - 2;

                var panel = $('div.result-panels div.result-panel#count');
                if (panel.length === 0) {
                    return false;
                }

                panel.empty();

                var zeroRow = $('
');
                zeroRow.addClass('empty-row');

                var firstRow = $('
');

                $.each(Array(count), function() {
                    var icon = $('');
                    icon.addClass('glyphicon glyphicon-user count-icon');

                    firstRow.append(icon);
                });

                var secondRow = $('
');

                var usersStr = String(count).slice(-1) === '1' ? 'пользователя' : 'пользователей';
                secondRow.append('Вы знакомы через ' + count + ' ' + usersStr + '');

                panel.append(zeroRow, firstRow, secondRow);

                return true;
            },
            write: function(data) {
                var group = $('div.result-panels div.result-panel ul.list-group');
                if (group.length === 0) {
                    return false;
                }

                group.find('li.list-group-item').remove();

                data.sequences.forEach(function(row) {
                    row = row.map(function(id) {
                        return data.users.filter(function(item) {
                            return item.uid === id
                        })[0];
                    });

                    var li = $('
');

                    var table = $('
');
                    li.append(table);

                    row.forEach(function(user) {
                        var title = 'title="
Пол: {1}

ДР: {2}

"'.format(
                            user.photo_100,
                            user.sex === 2 ? 'мужской' : user.sex === 1 ? 'женский' : 'не говорит',
                            user.bdate || 'не говорит'
                        );

                        var href = 'href="http://vk.com/id{0}"'.format(user.uid);

                        var cell = $('
');

                        cell.append('' + [user.first_name, user.last_name].join(' ') + '');
                        table.append(cell);
                    });

                    group.append(li);
                });

                group.find('[title]').tooltip({
                    html: true
                });

                return true;
            },
            draw: function(data) {
                var panel = $('div.result-panels div.result-panel#draw');
                if (panel.length === 0) {
                    return false;
                }

                panel.empty();

                var firstUser, secondUser;
                var sequence = data.sequences[0];
                if (sequence) {
                    firstUser = sequence[0];
                    secondUser = sequence[sequence.length - 1];
                }

                var pairs = [];

                data.sequences.forEach(function(item) {
                    item.reduce(function(a, b) {
                        pairs.push([a, b]);

                        return b;
                    });
                });

                pairs = pairs.filter(function(item, index) {
                    return pairs.filter(function(item1, index1) {
                        return index > index1 && (item[0] === item1[0] && item[1] === item1[1]);
                    }).length === 0;
                });

                var links = pairs.map(function(pair) {
                    return {
                        source: pair[0],
                        target: pair[1]
                    }
                });

                var nodes = {};

                links.forEach(function(link) {
                    var sourceUser = data.users.filter(function(item) {
                        return item.uid === link.source
                    })[0];

                    link.source = nodes[link.source] || (nodes[link.source] = {
                        name: link.source,
                        label: [sourceUser.first_name, sourceUser.last_name].join(' ')
                    });

                    var targetUser = data.users.filter(function(item) {
                        return item.uid === link.target
                    })[0];

                    link.target = nodes[link.target] || (nodes[link.target] = {
                        name: link.target,
                        label: [targetUser.first_name, targetUser.last_name].join(' ')
                    });
                });

                var width = panel.closest('.container').width(),
                    height = width * 0.5;

                var force = d3.layout.force()
                    .nodes(d3.values(nodes))
                    .links(links)
                    .size([width, height])
                    .linkDistance(150)
                    .charge(-100)
                    .on('tick', function() {
                        path.attr('d', function(d) {
                            return 'M' + d.source.x + ',' + d.source.y + ' ' + d.target.x + ',' + d.target.y;
                        });

                        circle.attr('transform', function(d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        });

                        text.attr('transform', function(d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        });
                    }).start();

                var svg = d3.select('div.result-panels div.result-panel#draw').append('svg')
                    .attr('width', width)
                    .attr('height', height);

                svg.append('defs').selectAll('marker')
                    .data([])
                    .enter().append('marker')
                    .attr('id', function(d) {
                        return d;
                    })
                    .attr('viewBox', '0 -5 10 10')
                    .attr('refX', 15)
                    .attr('refY', -1.5)
                    .attr('markerWidth', 8)
                    .attr('markerHeight', 8)
                    .attr('orient', 'auto')
                    .append('path')
                    .attr('d', 'M0,-5L10,0L0,5');

                var path = svg.append('g').selectAll('path')
                    .data(force.links())
                    .enter().append('path')
                    .attr('class', function(d) {
                        return 'link';
                    });

                var circle = svg.append('g').selectAll('circle')
                    .data(force.nodes())
                    .enter().append('circle')
                    .attr('r', 8)
                    .attr('class', function(d) {
                        if (d.name === firstUser || d.name === secondUser) return 'red';
                    })
                    .call(force.drag);

                var text = svg.append('g').selectAll('text')
                    .data(force.nodes())
                    .enter().append('text')
                    .attr('x', 12)
                    .attr('y', 3)
                    .text(function(d) {
                        return d.label;
                    });

                var container = panel.closest('.container');

                setInterval(function() {
                    width = container.width();
                    height = width * 0.5;

                    force.size([width, height]);

                    svg.attr('height', height);
                }, 2000);

                return true;
            }
        }
    }
}();<|endoftext|>


<commit_before>/*
 * Define nipapApp angular application
 */
var nipapApp = angular.module('nipapApp', [
	'ngRoute',
	'ui.bootstrap',
	'ngTagsInput',
	'nipapApp.controllers',
	'nipapApp.directives',
	'nipapApp.filters',
	'nipapApp.services'
]);

/*
 * App configuration
 */
nipapApp.config(function($routeProvider, $uibTooltipProvider) {

		/*
		 * Define application routes
		 */
		$routeProvider
			.when('/pool/add', {
				'controller': 'PoolAddController',
				'templateUrl': '/templates/pool_add.html'
			})
			.when('/pool/edit/:pool_id', {
				'controller': 'PoolEditController',
				'templateUrl': '/templates/pool_edit.html'
			})
			.when('/pool/list', {
				'controller': 'PoolListController',
				'templateUrl': '/templates/pool_list.html'
			})
			.when('/prefix/add/:allocation_method/:allocation_method_parameter?', {
				'controller': 'PrefixAddController',
				'templateUrl': '/templates/prefix_add.html'
			})
			.when('/prefix/edit/:prefix_id', {
				'controller': 'PrefixEditController',
				'templateUrl': '/templates/prefix_edit.html'
			})
			.when('/vrf/add', {
				'controller': 'VRFAddController',
				'templateUrl': '/templates/vrf_add.html'
			})
			.when('/vrf/edit/:vrf_id', {
				'controller': 'VRFEditController',
				'templateUrl': '/templates/vrf_edit.html'
			})
			.when('/vrf/list', {
				'controller': 'VRFListController',
				'templateUrl': '/templates/vrf_list.html'
			});

		/*
		 * Default options for tooltips
		 */
		$uibTooltipProvider
			.options({
				'placement': 'bottom',
				'popupDelay': 100
			});
});
<commit_msg>www: Disabled Angulars Strict Contextual Escaping<commit_after>/*
 * Define nipapApp angular application
 */
var nipapApp = angular.module('nipapApp', [
	'ngRoute',
	'ui.bootstrap',
	'ngTagsInput',
	'nipapApp.controllers',
	'nipapApp.directives',
	'nipapApp.filters',
	'nipapApp.services'
]);

/*
 * App configuration
 */
nipapApp.config(function($routeProvider, $uibTooltipProvider, $sceProvider) {

		/*
		 * Define application routes
		 */
		$routeProvider
			.when('/pool/add', {
				'controller': 'PoolAddController',
				'templateUrl': '/templates/pool_add.html'
			})
			.when('/pool/edit/:pool_id', {
				'controller': 'PoolEditController',
				'templateUrl': '/templates/pool_edit.html'
			})
			.when('/pool/list', {
				'controller': 'PoolListController',
				'templateUrl': '/templates/pool_list.html'
			})
			.when('/prefix/add/:allocation_method/:allocation_method_parameter?', {
				'controller': 'PrefixAddController',
				'templateUrl': '/templates/prefix_add.html'
			})
			.when('/prefix/edit/:prefix_id', {
				'controller': 'PrefixEditController',
				'templateUrl': '/templates/prefix_edit.html'
			})
			.when('/vrf/add', {
				'controller': 'VRFAddController',
				'templateUrl': '/templates/vrf_add.html'
			})
			.when('/vrf/edit/:vrf_id', {
				'controller': 'VRFEditController',
				'templateUrl': '/templates/vrf_edit.html'
			})
			.when('/vrf/list', {
				'controller': 'VRFListController',
				'templateUrl': '/templates/vrf_list.html'
			});

		/*
		 * Default options for tooltips
		 */
		$uibTooltipProvider
			.options({
				'placement': 'bottom',
				'popupDelay': 100
			});

		/*
		 * Disable Strict Contextual Escaping on the application. At
		 * this stage where the application is partly implemented
		 * outside AngularJS but still using AngularJS directives, it's
		 * really difficult to get things to work with the SCE feature
		 * enabled. Re-enable again when more of the application is
		 * implemented in AngularJS.
		 */
		$sceProvider.enabled(false);
});
<|endoftext|>


<commit_before>/**
 * Karma.js, a plus-plus clone for botkit
 *
 * SETUP:
 *   requires redis with custom storage method "karma"
 *
 * USAGE:
 *   <item>++ // increment score for item
 *   <item>-- // decrement score for item
 */

export default (controller) => {
  const cache = {};

  // ++
  controller.hears(
    "^([\\s\\w'@.\\-:]*)\\s*(\\+\\+)(?:\\s+(?:for|because|cause|cuz|as)\\s+(.+))?$",
    ['ambient'],
    (bot, message) => changeKarma(bot, message, true)
  );

  // --
  controller.hears(
    "^([\\s\\w'@.\\-:]*)\\s*(--|—)(?:\\s+(?:for|because|cause|cuz|as)\\s+(.+))?$",
    ['ambient'],
    (bot, message) => changeKarma(bot, message, false)
  );

  // score
  controller.hears(
    "score (for\\s)?(.*)",
    ['direct_mention', 'direct_message'],
    (bot, message) => printScore(bot, message)
  );

  const changeKarma = (bot, message, increment) => {
    let name = cleanName(message.match[1]);
    let reason = message.match[3];

    // Make sure we can do something valid
    if (!name && !cache[message.channel]) {
      return;
    }

    // Get name / reason from cache
    if (!name && !reason) {
      name = cache[message.channel].name;
      reason = cache[message.channel].reason;
    } else if (!name && reason) {
      name = cache[message.channel].name;
    }

    if (reason) {
      reason = reason.trim();
    }

    controller.storage.karma.get(name, (err, item) => {
      // We're creating a new item
      if (!item) {
        item = {
          id: name,
          score: 0,
          reasons: {},
        };
      }

      // Update score
      if (increment) {
        item.score++;
      } else {
        item.score--;
      }

      // Update reason
      if (reason) {
        // Save the reason if we haven't seen it before
        if (!item.reasons[reason]) {
          item.reasons[reason] = 0;
        }

        // Update the reason's score
        if (increment) {
          item.reasons[reason]++;
        } else {
          item.reasons[reason]--;
        }
      }

      // Save
      controller.storage.karma.save(item);

      // Cache for ++ and -- with no name
      cache[message.channel] = { name, reason };

      const points = item.score === 1 ? 'point' : 'points';

      // Send the message
      if (!reason) {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      } else {
        const are = item.reasons[reason] === 1 ? 'is' : 'are';
        bot.reply(
          message,
          `${name} has ${item.score} points, ${item.reasons[reason]} of which ${are} for ${reason}`
        );
      }
    });
  };

  const printScore = (bot, message) => {
    const name = cleanName(message.match[2]);
    controller.storage.karma.get(name, (err, item) => {
      if (!item) {
        bot.reply(message, `${name} has 0 points`);
        return;
      }

      const points = item.score === 1 ? 'point' : 'points';

      if (item.reasons.length > 0) {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      } else {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      }
    });
  };

  const cleanName = (name) => {
    if (name.charAt(0) === ':') {
      return name.replace(/(^\s*@)|([,\s]*$)/g, '').trim().toLowerCase();
    } else {
      return name.replace(/(^\s*@)|([,:\s]*$)/g, '').trim().toLowerCase();
    }
  };
}
<commit_msg>Add karma top and bottom lookup<commit_after>/**
 * Karma.js, a plus-plus clone for botkit
 *
 * SETUP:
 *   requires redis with custom storage method "karma"
 *
 * USAGE:
 *   <item>++ // increment score for item
 *   <item>-- // decrement score for item
 */

export default (controller) => {
  const cache = {};

  // ++
  controller.hears(
    "^([\\s\\w'@.\\-:]*)\\s*(\\+\\+)(?:\\s+(?:for|because|cause|cuz|as)\\s+(.+))?$",
    ['ambient'],
    (bot, message) => changeKarma(bot, message, true)
  );

  // --
  controller.hears(
    "^([\\s\\w'@.\\-:]*)\\s*(--|—)(?:\\s+(?:for|because|cause|cuz|as)\\s+(.+))?$",
    ['ambient'],
    (bot, message) => changeKarma(bot, message, false)
  );

  // score
  controller.hears(
    "score (for\\s)?(.*)",
    ['direct_mention', 'direct_message'],
    (bot, message) => printScore(bot, message)
  );

  // top [n]
  controller.hears(
    "top (\\d+)",
    ['direct_mention', 'direct_message'],
    (bot, message) => top(bot, message)
  );

  // bottom [n]
  controller.hears(
    "bottom (\\d+)",
    ['direct_mention', 'direct_message'],
    (bot, message) => bottom(bot, message)
  );

  const changeKarma = (bot, message, increment) => {
    let name = cleanName(message.match[1]);
    let reason = message.match[3];

    // Make sure we can do something valid
    if (!name && !cache[message.channel]) {
      return;
    }

    // Get name / reason from cache
    if (!name && !reason) {
      name = cache[message.channel].name;
      reason = cache[message.channel].reason;
    } else if (!name && reason) {
      name = cache[message.channel].name;
    }

    if (reason) {
      reason = reason.trim();
    }

    controller.storage.karma.get(name, (err, item) => {
      // We're creating a new item
      if (!item) {
        item = {
          id: name,
          score: 0,
          reasons: {},
        };
      }

      // Update score
      if (increment) {
        item.score++;
      } else {
        item.score--;
      }

      // Update reason
      if (reason) {
        // Save the reason if we haven't seen it before
        if (!item.reasons[reason]) {
          item.reasons[reason] = 0;
        }

        // Update the reason's score
        if (increment) {
          item.reasons[reason]++;
        } else {
          item.reasons[reason]--;
        }
      }

      // Save
      controller.storage.karma.save(item);

      // Cache for ++ and -- with no name
      cache[message.channel] = { name, reason };

      const points = item.score === 1 ? 'point' : 'points';

      // Send the message
      if (!reason) {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      } else {
        const are = item.reasons[reason] === 1 ? 'is' : 'are';
        bot.reply(
          message,
          `${name} has ${item.score} points, ${item.reasons[reason]} of which ${are} for ${reason}`
        );
      }
    });
  };

  const printScore = (bot, message) => {
    const name = cleanName(message.match[2]);
    controller.storage.karma.get(name, (err, item) => {
      if (!item) {
        bot.reply(message, `${name} has 0 points`);
        return;
      }

      const points = item.score === 1 ? 'point' : 'points';

      if (item.reasons.length > 0) {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      } else {
        bot.reply(message, `${name} has ${item.score} ${points}`);
      }
    });
  };

  const top = (bot, message) => {
    const amount = message.match[1];
    controller.storage.karma.all((err, items) => {
      const tops = [];

      for (const item of items) {
        tops.push({
          name: item.id,
          score: item.score,
        });
      }

      const sorted = tops.sort((a, b) => {
        return b.score - a.score;
      }).slice(0, amount);

      if (sorted.length > 0) {
        let reply = "";
        for (let i = 0; i < sorted.length; i++) {
          reply += `${i + 1}. ${sorted[i].name} : ${sorted[i].score}\n`;
        }
        bot.reply(message, reply);
      } else {
        bot.reply(message, "No scores to keep track of yet!");
      }
    }, { type: 'array' });
  };

  const bottom = (bot, message) => {
    const amount = message.match[1];
    controller.storage.karma.all((err, items) => {
      const tops = [];

      for (const item of items) {
        tops.push({
          name: item.id,
          score: item.score,
        });
      }

      const sorted = tops.sort((a, b) => {
        return b.score - a.score;
      }).reverse().slice(0, amount);

      if (sorted.length > 0) {
        let reply = "";
        for (let i = 0; i < sorted.length; i++) {
          reply += `${i + 1}. ${sorted[i].name} : ${sorted[i].score}\n`;
        }
        bot.reply(message, reply);
      } else {
        bot.reply(message, "No scores to keep track of yet!");
      }
    }, { type: 'array' });
  };

  const cleanName = (name) => {
    if (name.charAt(0) === ':') {
      return name.replace(/(^\s*@)|([,\s]*$)/g, '').trim().toLowerCase();
    } else {
      return name.replace(/(^\s*@)|([,:\s]*$)/g, '').trim().toLowerCase();
    }
  };
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http: *www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

'use strict';

describe('Controller: ParameterSelectCtrl', function () {

  // load the controller's module
  beforeEach(module('ocwUiApp'));

  var ParameterselectCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    ParameterselectCtrl = $controller('ParameterSelectCtrl', {
      $scope: scope
    });
  }));

  it('should initialize spatial and temporal range default values properly', function() {
    expect(scope.latMin).toBe(-90);
    expect(scope.latMax).toBe(90);
    expect(scope.lonMin).toBe(-180);
    expect(scope.lonMax).toBe(180);
    expect(scope.start).toBe("1900-01-01 00:00:00");
    expect(scope.end).toBe("2030-01-01 00:00:00");
  });

  it('should grab the default set of selected datasets from the service', function() {
    // We should get an object with no keys since the user hasn't selected any
    // datasets by default. Object.keys returns an array of all the user defined
    // keys in the object.
    expect(typeof scope.datasets).toBe('object');
    expect(Object.keys(scope.datasets).length).toBe(0);
  });

  it('should grab the default region select param object from the regionSelectParams service', function() {
    // The default display values aren't going to be changing any time soon. This test
    // is a bit of a duplicate since this is really testing functionality of the service.
    // Can't hurt to make sure that we're getting results though!
    expect(typeof scope.displayParams).toBe('object');
    expect(Object.keys(scope.displayParams).length).toBe(7);
  });

  it('should initialize misc. values properly', function() {
    expect(scope.runningEval).toBe(false);
    expect(scope.areInUserRegridState).toBe(false);
    expect(scope.latSliderVal).toBe(0);
    expect(scope.lonSliderVal).toBe(0);
  });

  it('should set the default datepicker settings', function() {
    // This tests the default values that get passed to the datepicker objects that we
    // initialize with a directive.
    expect(Object.keys(scope.datepickerSettings).length).toBe(2);
    expect(scope.datepickerSettings.changeMonth).toBe(true);
    expect(scope.datepickerSettings.changeYear).toBe(true);
  });

  it('should initialize the control disable function', function() {
    // Add to dummy values to datasets to make sure the disable function
    // triggers properly.
    scope.datasets.push(1);
    scope.datasets.push(2);
    expect(scope.shouldDisableControls()).toBe(false);
  });

  it('should initialize the disable evaluation button function', function() {
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
    scope.datasets.push(1);
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
    scope.datasets.push(2);
    expect(scope.shouldDisableEvaluateButton()).toBe(false);
    scope.runningEval = true;
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
  });

  it('should initialize the disable results view function', function() {
    inject(function($rootScope) {
      expect(scope.shouldDisableResultsView()).toBe(true);

      // Set evalResults to something other than the default value
      $rootScope.evalResults = "this is not an empty string";

      expect(scope.shouldDisableResultsView()).toBe(false);
    });
  });

  /*
   * TODO: $scope.$apply() in the controller is breaking this test. Need to
   * find a way to deal with that or rethink how we handle this test.
   *
   */
  /*
  it('should initialize the check parameters function', function() {
      // Set the displayParams values to be "out of bounds" values so checkParams
      // adjusts them properly.
      scope.displayParams.latMin = "-95";
      scope.displayParams.latMax = "95";
      scope.displayParams.lonMin = "-185";
      scope.displayParams.lonMax = "185";
      scope.displayParams.start = "1980-00-00 00:00:00";
      scope.displayParams.end = "2031-01-01 00:00:00";

      // If we don't remove the watch on datasets we end up with displayParam values
      // all being undefined (but only during testing, which is odd...)
      scope.unwatchDatasets();
      scope.checkParameters();

      expect(scope.displayParams.latMin).toBe(-90);
      expect(scope.displayParams.latMax).toBe(90);
      expect(scope.displayParams.lonMin).toBe(-180);
      expect(scope.displayParams.lonMax).toBe(180);
      expect(scope.displayParams.start).toBe('1980-01-01 00:00:00');
      expect(scope.displayParams.end).toBe('2030-01-01 00:00:00');
  });
  */

  /*
   * TODO: The backend call for this expects completely different data formats.
   * Additionally, there are many more URLs to mock now. Something has definitely
   * changed with how httpBackend functions or the way the code base is setup.
   */
  /*
  it('should properly set the results of running an evaluation', function() {
    inject(function($rootScope, $controller, $httpBackend) {
      var scope = $rootScope.$new();
      var ctrl = $controller("ParameterSelectCtrl", {$scope: scope});

      // Seed rootScope with a known URL for test queries and holder for eval results
      $rootScope.baseURL = "http://localhost:9876";
      $rootScope.evalResults = {};

      // Seed the displayParams so the query is properly formatted
      scope.displayParams.lonMin = -180;
      scope.displayParams.lonMax = 180;
      scope.displayParams.latMin = -90;
      scope.displayParams.latMax = 90;
      scope.displayParams.start = "1980-01-01";
      scope.displayParams.end = "2030-01-01";

      // The expected URL string that the frontend generates given this example set
      var urlString = "http://localhost:9876/rcmes/run/?" +
        "callback=JSON_CALLBACK&" +
        "endTime=2030-01-01%2000%3A00%3A00&" +
        "filelist=%2Fusr%2Flocal%2Frcmes%2FmodelsForUI%2Fprec.HRM3.ncep.monavg.nc&" +
        "latMax=90&" +
        "latMin=-90&" +
        "lonMax=180&" +
        "lonMin=-180&" +
        "metricOption=bias&" +
        "modelLatVarName=lat&" +
        "modelLonVarName=lon&" +
        "modelTimeVarName=time&" +
        "modelVarName=prec&" +
        "obsDatasetId=3&" +
        "obsParameterId=36&" +
        "regridOption=model&" +
        "startTime=1980-01-01%2000%3A00%3A00&" +
        "timeRegridOption=monthly";

      // Example dataset configuration for the test.
      scope.datasets = [
        {
          "isObs"         : 1,
          "id"            : "3",
          "name"          : "Tropical Rainfall Measuring Mission Dataset",
          "param"         : "36",
          "paramName"     : "TRMM v.6 Monthly Precipitation",
          "latlonVals"    : {"latMin" : -90, "latMax" : 90, "lonMin" : -180, "lonMax" : 180},
          "lat"           : "N/A",
          "lon"           : "N/A",
          "timeVals"      : {"start" : "1998-01-01 00:00:00",
          "end"           : "2010-01-01 00:00:00"},
          "time"          : "N/A",
          "shouldDisplay" : true,
          "regrid"        : false
          },{
          "isObs"         : 0,
          "id"            : "/usr/local/rcmes/modelsForUI/prec.HRM3.ncep.monavg.nc",
          "name"          : "prec.HRM3.ncep.monavg.nc",
          "param"         : "prec",
          "paramName"     : "prec",
          "lat"           : "lat",
          "lon"           : "lon",
          "latlonVals"    : {"latMin" : "15.25",
          "latMax"        : "75.25",
          "lonMin"        : "-159.75",
          "lonMax"        : "-29.75"},
          "time"          : "time",
          "timeVals"      : {"start":"1980-01-01 00:00:00",
          "end"           : "2004-12-01 00:00:00"},
          "shouldDisplay" : true,
          "regrid"        : false
        }
      ];

      $httpBackend.expectGET('http://localhost:8082/processing/metrics/').respond(
        200, {'data': {'metrics': ['foo', 'bar']}}
      )
      $httpBackend.expectPOST('http://localhost:9876/processing/run_evaluation/').respond(200)
      $httpBackend.expectGET('views/main.html').respond(200)
      $httpBackend.expectJSONP(urlString).respond(200,
          {'comparisonPath': '/fake/path1',
           'modelPath': '/fake/path2',
           'obsPath': '/fake/path3'});

      console.log('here')
      scope.runEvaluation();
      console.log('here1')
      $httpBackend.flush();
      console.log('here2')

      expect($rootScope.evalResults.comparisonPath).toBe('path1');
      expect($rootScope.evalResults.modelPath).toBe('path2');
      expect($rootScope.evalResults.obsPath).toBe('path3');
    });
  });
  */
});
<commit_msg>CLIMATE-355 - Remove outdated evaluation run test<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http: *www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

'use strict';

describe('Controller: ParameterSelectCtrl', function () {

  // load the controller's module
  beforeEach(module('ocwUiApp'));

  var ParameterselectCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    ParameterselectCtrl = $controller('ParameterSelectCtrl', {
      $scope: scope
    });
  }));

  it('should initialize spatial and temporal range default values properly', function() {
    expect(scope.latMin).toBe(-90);
    expect(scope.latMax).toBe(90);
    expect(scope.lonMin).toBe(-180);
    expect(scope.lonMax).toBe(180);
    expect(scope.start).toBe("1900-01-01 00:00:00");
    expect(scope.end).toBe("2030-01-01 00:00:00");
  });

  it('should grab the default set of selected datasets from the service', function() {
    // We should get an object with no keys since the user hasn't selected any
    // datasets by default. Object.keys returns an array of all the user defined
    // keys in the object.
    expect(typeof scope.datasets).toBe('object');
    expect(Object.keys(scope.datasets).length).toBe(0);
  });

  it('should grab the default region select param object from the regionSelectParams service', function() {
    // The default display values aren't going to be changing any time soon. This test
    // is a bit of a duplicate since this is really testing functionality of the service.
    // Can't hurt to make sure that we're getting results though!
    expect(typeof scope.displayParams).toBe('object');
    expect(Object.keys(scope.displayParams).length).toBe(7);
  });

  it('should initialize misc. values properly', function() {
    expect(scope.runningEval).toBe(false);
    expect(scope.areInUserRegridState).toBe(false);
    expect(scope.latSliderVal).toBe(0);
    expect(scope.lonSliderVal).toBe(0);
  });

  it('should set the default datepicker settings', function() {
    // This tests the default values that get passed to the datepicker objects that we
    // initialize with a directive.
    expect(Object.keys(scope.datepickerSettings).length).toBe(2);
    expect(scope.datepickerSettings.changeMonth).toBe(true);
    expect(scope.datepickerSettings.changeYear).toBe(true);
  });

  it('should initialize the control disable function', function() {
    // Add to dummy values to datasets to make sure the disable function
    // triggers properly.
    scope.datasets.push(1);
    scope.datasets.push(2);
    expect(scope.shouldDisableControls()).toBe(false);
  });

  it('should initialize the disable evaluation button function', function() {
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
    scope.datasets.push(1);
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
    scope.datasets.push(2);
    expect(scope.shouldDisableEvaluateButton()).toBe(false);
    scope.runningEval = true;
    expect(scope.shouldDisableEvaluateButton()).toBe(true);
  });

  it('should initialize the disable results view function', function() {
    inject(function($rootScope) {
      expect(scope.shouldDisableResultsView()).toBe(true);

      // Set evalResults to something other than the default value
      $rootScope.evalResults = "this is not an empty string";

      expect(scope.shouldDisableResultsView()).toBe(false);
    });
  });

  /*
   * TODO: $scope.$apply() in the controller is breaking this test. Need to
   * find a way to deal with that or rethink how we handle this test.
   *
   */
  /*
  it('should initialize the check parameters function', function() {
      // Set the displayParams values to be "out of bounds" values so checkParams
      // adjusts them properly.
      scope.displayParams.latMin = "-95";
      scope.displayParams.latMax = "95";
      scope.displayParams.lonMin = "-185";
      scope.displayParams.lonMax = "185";
      scope.displayParams.start = "1980-00-00 00:00:00";
      scope.displayParams.end = "2031-01-01 00:00:00";

      // If we don't remove the watch on datasets we end up with displayParam values
      // all being undefined (but only during testing, which is odd...)
      scope.unwatchDatasets();
      scope.checkParameters();

      expect(scope.displayParams.latMin).toBe(-90);
      expect(scope.displayParams.latMax).toBe(90);
      expect(scope.displayParams.lonMin).toBe(-180);
      expect(scope.displayParams.lonMax).toBe(180);
      expect(scope.displayParams.start).toBe('1980-01-01 00:00:00');
      expect(scope.displayParams.end).toBe('2030-01-01 00:00:00');
  });
  */
});
<|endoftext|>