<commit_before>(function(exports) {

  function mixin(object, source, options) {
    var chain = true;

    if (options === false) {
      chain = false;
    } else if (_.isObject(options) && 'chain' in options) {
      chain = options.chain;
    }

    //options = options || {};

    // set each method (in source) for object
    for(methodName in source) {
      prop = source[methodName];
      // this will set the methods to the global stats
      object[methodName] = prop;

      if (_.isFunction(prop)) {
        // this will set the methods to the wrapped object.
        // But now, we already have a collection defined,
        // so we just pass it to the original function;
        // object.prototype[methodName] = prop;
        object.prototype[methodName] = (function(prop, options){

          function mixed() {
            //if (_.isEmpty(arguments))
              //arguments = options.args;

            // $wrapped is just one (or) the first argument,
            // so we pass to the first arguments;

            if (chain || !_.isEmpty(prop.prototype)) {

              var args = [this];
              Array.prototype.push.apply(args, arguments);

              // in this mixin we just execute the method, and mantain the wrapped
              prop.apply(this, args);

              // this.$wrapped = prop.apply(this, args);

              return this;
            }

            var args = [];
            Array.prototype.push.apply(args, arguments);

            return prop.apply(this, args);
          }

          if (!_.isEmpty(prop.prototype)) {
            //mixin.call(this, mixed, prop.prototype, {chain: false, args: arguments});

            return mixed;
          } else {
            return mixed;
          }

          return mixed;

          //F.prototype = prop.prototype;

        }.call(object, prop, options));
      } else {
        // only mix functions
        // console.log('do nothing?', methodName);
      }
    }

    return object;
  }

  function mixin2(object, source, chain) {
    chain = !chain;

    for(var methodName in source) {
      if (_.isFunction(source[methodName])) {
        object.prototype[methodName] = function(method, methodName) {
          function mixed() {
            if (chain) {
              var args = [this];
              Array.prototype.push.apply(args, arguments);

              method.apply(this, args);

              // return the current class when mixed
              return this;
            }

            var args = [];
            Array.prototype.push.apply(args, arguments);

            return prop.apply(this, args);
          }
          return mixed;
        }.call(source, source[methodName], methodName);
      } else {
        object.prototype[methodName] = source[methodName];
      }
    }
    return object;
  }

  var ai = {};

  var extensions = [];
  var extensions_proto = [];

  function Class(name, methods, inherits) {

    var classed = {};

    methods = methods || {};

    // methods = _.defaults(methods, {
    //   $pk: 'id'
    // });

    // prevent injection on eval
    name = name.toLowerCase().replace(/[^a-z0-1_A-Z]/g, '');
    var Name = _.capitalize(name.replace(/[^a-z0-1_A-Z]/g, ''));
    var NameWrapper = (Name + "Wrapper").replace(/[^a-z0-1_A-Z]/g, '');

    ai[name] = 1;

    var defaults = methods.$defaults || {};

    function hasMany() {
      if (methods.$hasMany) {
        _.each(methods.$hasMany, function(r, k) {
          defaults[k] = r.$constructor();
        });
      }
    }

    eval('function '+Name+'(o){\
      hasMany();\
      var defs = _.defaults(_.cloneDeep(defaults), {\
        id: ai[name]\
      });\
      o = _.defaults(o || {}, defs);\
      _.assign(this,o);\
      ai[name] += 1;\
    }');

    eval('function '+NameWrapper+'(value){\
      var u = new '+Name+'(value);\
      _.assign(this,u);\
      this.$wrapped = u;\
    }');

    var constructor;

    eval('var '+name+' = constructor = function '+name+'(value){\
      if (value instanceof '+NameWrapper+')\
        return value;\
      return new '+NameWrapper+'(value);\
    }');

    // eval(name+'.$data = [];');
    // eval(name+'.$current = null;');
    // eval(name+'.$current = $current.bind('+name+');');
    // eval(name+'.$add = $add.bind('+name+');');

    var listeners = {};

    function dispatch(listener) {
      var args = Array.prototype.slice.call(arguments, 1);

      if (listeners[listener]) {
        _.each(listeners[listener], function(callback) {
          callback.apply(this, args);
        }, this);
      }

      return;
    }

    function Classy() {
      var current = null;
      var data = [];
      var indexed = {};
      var index = methods.$index || 'id';

      this.$on = function(listener, callback) {
        listeners[listener] = listeners[listener] || [];

        if (_.isFunction(callback))
          listeners[listener].push(callback);

        return this;
      };

      this.$constructor = function() {
        return Class(name, methods);
      };

      this.$current = function (c) {
        if (!_.isUndefined(c)) {
          current = (c && c.id) ? this.$data(c) : null;
          return this;
        } else {
          return current;
        }
      };

      this.$first = function() {
        return _.first(data);
      };

      this.$last = function() {
        return _.last(data);
      };

      this.$next = function() {
        var k = _.indexOf(data, this.$current());

        return (k > -1) ? (data[k+1] ? data[k+1] : false) : false;
      };

      this.$prev = function() {
        var k = _.indexOf(data, this.$current());

        return (k > -1) ? (data[k-1] ? data[k-1] : false) : false;
      };

      this.$goNext = function() {
        var k = _.indexOf(data, this.$current());

        this.$current(data[k+1] ? data[k+1] : this.$current());

        return this;
      };

      this.$goPrev = function() {
        var k = _.indexOf(data, this.$current());

        this.$current(data[k-1] ? data[k-1] : this.$current());

        return this;
      };

      this.$add = function(u) {
        u = constructor(u);

        data.push(u);
        indexed[u[index]] = u;

        dispatch.call(this, '$add', u);

        return this;
      };

      this.$load = function(data) {
        _.each(data, function(d) {
          this(d).$add();
        }, this);

        return this;
      };

      this.$removeAll = function() {
        data = [];
        indexed = {};

        ai[name] = 1;
        current = null;

        dispatch.call(this, '$removeAll');

        return this;
      };

      this.$removeAt = function(at, n) {
        var rem = data.splice(at, n || 1);

        _.each(rem, function(k) {
          if (_.isEqual(current, k))
            current = null;
          delete indexed[k[index]];
        });

        delete rem;

        dispatch.call(this, '$removeAt', at, n);

        return this;
      };

      this.$remove = function(u) {
        delete indexed[u[index]];
        _.pull(data, u);

        if (_.isEqual(current, u))
          current = null;

        dispatch.call(this, '$remove', u);

        return this;
      };

      this.$data = function(i) {
        return _.isFinite(i)
          ? data[i]
          : (_.isObject(i) ? _.find(data, i) : data);
      };

      this.$filter = function(ff) {
        return _.filter(data, ff);
      };

      this.$find = function(ff) {
        return _.find(data, ff);
      };

      this.$export = function() {
        return _.filter(data, function(d) {
          return d.$value();
        });
      };

      this.$change = function(a, b) {
        var k;
        if (_.isFinite(a))
          k = a;
        else
          k = _.findIndex(data, {id: a.id});

        if (data[k])
          data[k] = this(b);

        return this;
      };

      this.$set = function(u, key, value) {
        if (_.isArray(key)) {
          // TODO
        } else if(_.isPlainObject(key)) {
          this.$change(a, b);
        } else {
          u[key] = value;
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$push = function(u, key, value) {

        if (_.isArray(u[key])) {
          u[key].push(value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$pull = function(u, key, value) {
        if (_.isArray(u[key])) {
          _.pull(u[key], value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$concat = function(u, key, value) {
        if (_.isArray(u[key])) {
          u[key] = u[key].concat(value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$indexed = function(k) {
        return k ? indexed[k] : indexed;
      };

      // FIXME
      _.each(extensions, function(e) {
        if (e.options.chain)
          _.assign(this, e.extension);
      }, this);

      // FIXME
      _.each(extensions_proto, function(e) {
        if (e.options.chain)
          _.assign(this, e.extension);
      }, this);

      // FIXME
      if (methods && !methods.prototype)
        _.assign(this, methods);
    }

    // methods only for the constructor not his instances
    function ClassyProto() {}

    // unchainable methods
    function ClassyUnchain() {}

    ClassyUnchain.prototype.$value = function(u) {
      var n = {};

      _.each(this, function(v, k) {
        if (_.indexOf(k, '$') !== 0)
          n[k] = v;
      }, this);

      return n;
    };

    if (methods && methods.$unchain) {
      mixin(ClassyUnchain, methods.$unchain, false);
    }

    // FIXME
    if (methods && methods.prototype) {
      Classy.prototype = methods.prototype;
    }

    if (inherits)
      eval('mixin('+name+', inherits, true);');

    function $extend(_o) {
      eval('mixin('+name+', _o, true);');
      return this;
    }
    eval(''+name+'.$extend = $extend;');

    // function $current(c) {
    //   if (c) {
    //     eval(name+'.$current = c');
    //     return this;
    //   } else {
    //     return eval(name+'.$current');
    //   }
    // }
    // function $add(u) {
    //   eval(name+'.$data.push(u);');
    //   return this;
    // };

    // _.each(new Classy(), function(d, k) {
    //   eval(''+name+'.'+k+' = d;');
    // });

    eval('mixin('+name+', new Classy(), true);');

    eval('mixin('+name+', new ClassyUnchain(), false);');

    // eval('mixin('+name+', '+name+');');
    eval(NameWrapper+'.prototype = '+name+'.prototype;');

    // private methods for the Constructor only
    _.each(new ClassyProto(), function(d, k) {
      eval(''+name+'.'+k+' = d;');
    });

    return eval(name);
  }

  Class.$extend = function(obj, options) {
    _.defaults(options, {
      chain: true
    });

    obj = {
      extension: obj,
      options: options
    };

    if (_.isPlainObject(obj)) {
      extensions.push(obj);
    } else {
      extensions_proto.push(obj);
    }

    return Class;
  };

  if (exports.Classy) {
    console.info("The library Classy is already loaded.");
  } else {
    exports.Classy = Class;
  }

}(window));
<commit_msg>fixed removeAll data by not removing the referenced with other variables<commit_after>(function(exports) {

  function mixin(object, source, options) {
    var chain = true;

    if (options === false) {
      chain = false;
    } else if (_.isObject(options) && 'chain' in options) {
      chain = options.chain;
    }

    //options = options || {};

    // set each method (in source) for object
    for(methodName in source) {
      prop = source[methodName];
      // this will set the methods to the global stats
      object[methodName] = prop;

      if (_.isFunction(prop)) {
        // this will set the methods to the wrapped object.
        // But now, we already have a collection defined,
        // so we just pass it to the original function;
        // object.prototype[methodName] = prop;
        object.prototype[methodName] = (function(prop, options){

          function mixed() {
            //if (_.isEmpty(arguments))
              //arguments = options.args;

            // $wrapped is just one (or) the first argument,
            // so we pass to the first arguments;

            if (chain || !_.isEmpty(prop.prototype)) {

              var args = [this];
              Array.prototype.push.apply(args, arguments);

              // in this mixin we just execute the method, and mantain the wrapped
              prop.apply(this, args);

              // this.$wrapped = prop.apply(this, args);

              return this;
            }

            var args = [];
            Array.prototype.push.apply(args, arguments);

            return prop.apply(this, args);
          }

          if (!_.isEmpty(prop.prototype)) {
            //mixin.call(this, mixed, prop.prototype, {chain: false, args: arguments});

            return mixed;
          } else {
            return mixed;
          }

          return mixed;

          //F.prototype = prop.prototype;

        }.call(object, prop, options));
      } else {
        // only mix functions
        // console.log('do nothing?', methodName);
      }
    }

    return object;
  }

  function mixin2(object, source, chain) {
    chain = !chain;

    for(var methodName in source) {
      if (_.isFunction(source[methodName])) {
        object.prototype[methodName] = function(method, methodName) {
          function mixed() {
            if (chain) {
              var args = [this];
              Array.prototype.push.apply(args, arguments);

              method.apply(this, args);

              // return the current class when mixed
              return this;
            }

            var args = [];
            Array.prototype.push.apply(args, arguments);

            return prop.apply(this, args);
          }
          return mixed;
        }.call(source, source[methodName], methodName);
      } else {
        object.prototype[methodName] = source[methodName];
      }
    }
    return object;
  }

  var ai = {};

  var extensions = [];
  var extensions_proto = [];

  function Class(name, methods, inherits) {

    var classed = {};

    methods = methods || {};

    // methods = _.defaults(methods, {
    //   $pk: 'id'
    // });

    // prevent injection on eval
    name = name.toLowerCase().replace(/[^a-z0-1_A-Z]/g, '');
    var Name = _.capitalize(name.replace(/[^a-z0-1_A-Z]/g, ''));
    var NameWrapper = (Name + "Wrapper").replace(/[^a-z0-1_A-Z]/g, '');

    ai[name] = 1;

    var defaults = methods.$defaults || {};

    function hasMany() {
      if (methods.$hasMany) {
        _.each(methods.$hasMany, function(r, k) {
          defaults[k] = r.$constructor();
        });
      }
    }

    eval('function '+Name+'(o){\
      hasMany();\
      var defs = _.defaults(_.cloneDeep(defaults), {\
        id: ai[name]\
      });\
      o = _.defaults(o || {}, defs);\
      _.assign(this,o);\
      ai[name] += 1;\
    }');

    eval('function '+NameWrapper+'(value){\
      var u = new '+Name+'(value);\
      _.assign(this,u);\
      this.$wrapped = u;\
    }');

    var constructor;

    eval('var '+name+' = constructor = function '+name+'(value){\
      if (value instanceof '+NameWrapper+')\
        return value;\
      return new '+NameWrapper+'(value);\
    }');

    // eval(name+'.$data = [];');
    // eval(name+'.$current = null;');
    // eval(name+'.$current = $current.bind('+name+');');
    // eval(name+'.$add = $add.bind('+name+');');

    var listeners = {};

    function dispatch(listener) {
      var args = Array.prototype.slice.call(arguments, 1);

      if (listeners[listener]) {
        _.each(listeners[listener], function(callback) {
          callback.apply(this, args);
        }, this);
      }

      return;
    }

    function Classy() {
      var current = null;
      var data = [];
      var indexed = {};
      var index = methods.$index || 'id';

      this.$on = function(listener, callback) {
        listeners[listener] = listeners[listener] || [];

        if (_.isFunction(callback))
          listeners[listener].push(callback);

        return this;
      };

      this.$constructor = function() {
        return Class(name, methods);
      };

      this.$current = function (c) {
        if (!_.isUndefined(c)) {
          current = (c && c.id) ? this.$data(c) : null;
          return this;
        } else {
          return current;
        }
      };

      this.$first = function() {
        return _.first(data);
      };

      this.$last = function() {
        return _.last(data);
      };

      this.$next = function() {
        var k = _.indexOf(data, this.$current());

        return (k > -1) ? (data[k+1] ? data[k+1] : false) : false;
      };

      this.$prev = function() {
        var k = _.indexOf(data, this.$current());

        return (k > -1) ? (data[k-1] ? data[k-1] : false) : false;
      };

      this.$goNext = function() {
        var k = _.indexOf(data, this.$current());

        this.$current(data[k+1] ? data[k+1] : this.$current());

        return this;
      };

      this.$goPrev = function() {
        var k = _.indexOf(data, this.$current());

        this.$current(data[k-1] ? data[k-1] : this.$current());

        return this;
      };

      this.$add = function(u) {
        u = constructor(u);

        data.push(u);
        indexed[u[index]] = u;

        dispatch.call(this, '$add', u);

        return this;
      };

      this.$load = function(data) {
        this.$removeAll();

        _.each(data, function(d) {
          this(d).$add();
        }, this);

        return this;
      };

      this.$removeAll = function() {
        data.length = 0;
        // WARNING
        // to not remove the assigment, use the code above
        // for (var j in indexed) delete indexed[j];
        indexed = {};

        ai[name] = 1;
        current = null;

        dispatch.call(this, '$removeAll');

        return this;
      };

      this.$removeAt = function(at, n) {
        var rem = data.splice(at, n || 1);

        _.each(rem, function(k) {
          if (_.isEqual(current, k))
            current = null;
          delete indexed[k[index]];
        });

        delete rem;

        dispatch.call(this, '$removeAt', at, n);

        return this;
      };

      this.$remove = function(u) {
        delete indexed[u[index]];
        _.pull(data, u);

        if (_.isEqual(current, u))
          current = null;

        dispatch.call(this, '$remove', u);

        return this;
      };

      this.$data = function(i) {
        return _.isFinite(i)
          ? data[i]
          : (_.isObject(i) ? _.find(data, i) : data);
      };

      this.$filter = function(ff) {
        return _.filter(data, ff);
      };

      this.$find = function(ff) {
        return _.find(data, ff);
      };

      this.$export = function() {
        return _.filter(data, function(d) {
          return d.$value();
        });
      };

      this.$change = function(a, b) {
        var k;
        if (_.isFinite(a))
          k = a;
        else
          k = _.findIndex(data, {id: a.id});

        if (data[k])
          data[k] = this(b);

        return this;
      };

      this.$set = function(u, key, value) {
        if (_.isArray(key)) {
          // TODO
        } else if(_.isPlainObject(key)) {
          this.$change(a, b);
        } else {
          u[key] = value;
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$push = function(u, key, value) {

        if (_.isArray(u[key])) {
          u[key].push(value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$pull = function(u, key, value) {
        if (_.isArray(u[key])) {
          _.pull(u[key], value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$concat = function(u, key, value) {
        if (_.isArray(u[key])) {
          u[key] = u[key].concat(value);
          u.$wrapped[key] = u[key];
        }

        return this;
      };

      this.$indexed = function(k) {
        return k ? indexed[k] : indexed;
      };

      // FIXME
      _.each(extensions, function(e) {
        if (e.options.chain)
          _.assign(this, e.extension);
      }, this);

      // FIXME
      _.each(extensions_proto, function(e) {
        if (e.options.chain)
          _.assign(this, e.extension);
      }, this);

      // FIXME
      if (methods && !methods.prototype)
        _.assign(this, methods);
    }

    // methods only for the constructor not his instances
    function ClassyProto() {}

    // unchainable methods
    function ClassyUnchain() {}

    ClassyUnchain.prototype.$value = function(u) {
      var n = {};

      _.each(this, function(v, k) {
        if (_.indexOf(k, '$') !== 0)
          n[k] = v;
      }, this);

      return n;
    };

    if (methods && methods.$unchain) {
      mixin(ClassyUnchain, methods.$unchain, false);
    }

    // FIXME
    if (methods && methods.prototype) {
      Classy.prototype = methods.prototype;
    }

    if (inherits)
      eval('mixin('+name+', inherits, true);');

    function $extend(_o) {
      eval('mixin('+name+', _o, true);');
      return this;
    }
    eval(''+name+'.$extend = $extend;');

    // function $current(c) {
    //   if (c) {
    //     eval(name+'.$current = c');
    //     return this;
    //   } else {
    //     return eval(name+'.$current');
    //   }
    // }
    // function $add(u) {
    //   eval(name+'.$data.push(u);');
    //   return this;
    // };

    // _.each(new Classy(), function(d, k) {
    //   eval(''+name+'.'+k+' = d;');
    // });

    eval('mixin('+name+', new Classy(), true);');

    eval('mixin('+name+', new ClassyUnchain(), false);');

    // eval('mixin('+name+', '+name+');');
    eval(NameWrapper+'.prototype = '+name+'.prototype;');

    // private methods for the Constructor only
    _.each(new ClassyProto(), function(d, k) {
      eval(''+name+'.'+k+' = d;');
    });

    return eval(name);
  }

  Class.$extend = function(obj, options) {
    _.defaults(options, {
      chain: true
    });

    obj = {
      extension: obj,
      options: options
    };

    if (_.isPlainObject(obj)) {
      extensions.push(obj);
    } else {
      extensions_proto.push(obj);
    }

    return Class;
  };

  if (exports.Classy) {
    console.info("The library Classy is already loaded.");
  } else {
    exports.Classy = Class;
  }

}(window));
<|endoftext|>


<commit_before>var app = angular.module('lastfmApp', ['ui.bootstrap']);

app.controller('artistsCtl', function($scope, $http, $window, $cacheFactory) {

    $http.get('iso3116-countries.json')
        .success(function(response) {
            $scope.countries = response.countries.country;
            $scope.country = "Australia";
            // load the australia country once we have a list of countries
            getArtists($scope.country);

        })
        .error(function() {
            $window.alert("could not get countries list");
        });

    $scope.currentPage = 1;
    $scope.artists = [];
    $scope.countries = [];

    function getArtists() {

        $scope.artists = null;
        $scope.loadStatus = "Loading from last.fm....";

		var encCountry = encodeURI($scope.country);

	$http( { method: 'GET', url: 'server.php', params: { limit : 5, page: $scope.currentPage, country: encCountry }, cache: true })

        .success(function(response, status, headers, config) {
            // if we flip through the country list quickly there may be a previous requests with a country name different to the current $scope.country
			//  lets not display anything from an old stale query
			if (config.params.country != encodeURI($scope.country) && config.params.page != $scope.currentPage)
				{
                    return;
				}

                if (response.topartists && response.topartists['@attr'] && response.topartists['@attr'].total > 0) {
                    $scope.totalItems = response.topartists['@attr'].total;
                }

                if ($scope.totalItems > 1000000 *5) {
                    $scope.totalItems = 1000000 *5 -5;
					$scope.hasMore = true;
                }
				else
				{
					$scope.hasMore = false;
				}

                if (response.error) {
                    $scope.errorCode = "LFM123" + response.error;
                    $scope.artists = null;
                    return;

                }

                if (response.topartists && response.topartists.artist && response.topartists.artist.length > 0) {
                    // last.fm api is buggy... it often returns too many results. It seems to handle the page and limit incorrectly.
                    $scope.artists = response.topartists.artist.slice(Math.max(response.topartists.artist.length - 5, 0));
                    $scope.loadStatus = null;
                    return;
                }

				if (response.topartists && response.topartists.artist.length == 0 && response.topartists['@attr'].totalPages > $scope.currentPage)
					{
						$scope.artists = null;
						$scope.loadStatus = "Last.fm could not load this page " + $scope.currentPage + ". Try browsing to a lower page number.";
						return;
					}

				if (response.topartists && response.topartists.artist && response.topartists.artist.length == 0) {
                    // last.fm api is buggy... it often returns too many results. It seems to handle the page and limit incorrectly.
                    $scope.artists = null;
                    $scope.loadStatus = "No results were found for " + $scope.country;
                    return;
                }

                $scope.artists = null;
                $scope.errorCode = "LFM121";

            })
            .error(function(data, status, headers, config) {
                $scope.loadStatus = "Error communicating with server. If this error persists, please contact support@support.com and quote error LFM122";
                $scope.artists = null;

            })
    }

    $scope.pageChanged = function() {
        //alert('pageChanged');
        getArtists();
    }

    $scope.countryChanged = function() {
        //alert('country changed to ' + $country );
        switch ($scope.country) {
            case "Bonaire, Sint Eustatius and Saba":
            case "Bosnia and Herzegovina":
            case "Cabo Verde":
            case "C\xF4te d\'Ivoire":
            case "Bosnia and Herzegovina":
            case "Holy See":
            case "Libya":
            case "Palestine, State of":
            case "R\xE9union":
                {
                    $scope.artists = null;
                    $scope.loadStatus = $scope.country + " is not supported at this time.";
                    return;
                }
        }

		$scope.currentPage = 1;
		$scope.totalItems = 0;
        getArtists();
    }

    $scope.countrySelected = function(country) {
        $window.alert('Country selected is ' + country);

    }

});
<commit_msg>bug fix when selecting an invalid country<commit_after>var app = angular.module('lastfmApp', ['ui.bootstrap']);

app.controller('artistsCtl', function($scope, $http, $window, $cacheFactory) {

    $http.get('iso3116-countries.json')
        .success(function(response) {
            $scope.countries = response.countries.country;
            $scope.country = "Australia";
            // load the australia country once we have a list of countries
            getArtists($scope.country);

        })
        .error(function() {
            $window.alert("could not get countries list");
        });

    $scope.currentPage = 1;
    $scope.artists = [];
    $scope.countries = [];

    function getArtists() {

        $scope.artists = null;
        $scope.loadStatus = "Loading from last.fm....";

		var encCountry = encodeURI($scope.country);

	$http( { method: 'GET', url: 'server.php', params: { limit : 5, page: $scope.currentPage, country: encCountry }, cache: true })

        .success(function(response, status, headers, config) {
            // if we flip through the country list quickly there may be a previous requests with a country name different to the current $scope.country
			//  lets not display anything from an old stale query
			if (config.params.country != encodeURI($scope.country) && config.params.page != $scope.currentPage)
				{
                    return;
				}

                if (response.topartists && response.topartists['@attr'] && response.topartists['@attr'].total > 0) {
                    $scope.totalItems = response.topartists['@attr'].total;
                }

                if ($scope.totalItems > 1000000 *5) {
                    $scope.totalItems = 1000000 *5 -5;
					$scope.hasMore = true;
                }
				else
				{
					$scope.hasMore = false;
				}

                if (response.error) {
                    $scope.errorCode = "LFM123" + response.error;
                    $scope.artists = null;
                    return;

                }

                if (response.topartists && response.topartists.artist && response.topartists.artist.length > 0) {
                    // last.fm api is buggy... it often returns too many results. It seems to handle the page and limit incorrectly.
                    $scope.artists = response.topartists.artist.slice(Math.max(response.topartists.artist.length - 5, 0));
                    $scope.loadStatus = null;
                    return;
                }

				if (response.topartists && response.topartists.artist.length == 0 && response.topartists['@attr'].totalPages > $scope.currentPage)
					{
						$scope.artists = null;
						$scope.loadStatus = "Last.fm could not load this page " + $scope.currentPage + ". Try browsing to a lower page number.";
						return;
					}

				if (response.topartists && response.topartists.artist && response.topartists.artist.length == 0) {
                    // last.fm api is buggy... it often returns too many results. It seems to handle the page and limit incorrectly.
                    $scope.artists = null;
                    $scope.loadStatus = "No results were found for " + $scope.country;
                    return;
                }

                $scope.artists = null;
                $scope.errorCode = "LFM121";

            })
            .error(function(data, status, headers, config) {
                $scope.loadStatus = "Error communicating with server. If this error persists, please contact support@support.com and quote error LFM122";
                $scope.artists = null;

            })
    }

    $scope.pageChanged = function() {
        //alert('pageChanged');
        getArtists();
    }

    $scope.countryChanged = function() {
        //alert('country changed to ' + $country );
        switch ($scope.country) {
            case "Bonaire, Sint Eustatius and Saba":
            case "Bosnia and Herzegovina":
            case "Cabo Verde":
            case "C\xF4te d\'Ivoire":
            case "Bosnia and Herzegovina":
            case "Holy See":
            case "Libya":
            case "Palestine, State of":
            case "R\xE9union":
                {
                    $scope.artists = null;
					$scope.totalItems = 0;
                    $scope.loadStatus = $scope.country + " is not supported at this time.";
					$scope.hasMore = false;
                    return;
                }
        }

		$scope.currentPage = 1;
		$scope.totalItems = 0;
        getArtists();
    }

    $scope.countrySelected = function(country) {
        $window.alert('Country selected is ' + country);

    }

});
<|endoftext|>


<commit_before>/**
 * Extract.js
 *
 * https://github.com/jostw/extract.js
 *
 * Copyright (c) 2014 jos
 * Licensed under the MIT license.
 */

"use strict";

(function() {
    var Extract = function(name) {
        this.name = name || "extract";
    };

    Extract.prototype.init = function(selector) {
        var query = document.querySelectorAll(selector +" [data-"+ this.name +"]"),

            i = 0,
            length = query.length,

            model = {};

        for( ; i < length; i++) {
            var item = query[i],

                key = item.attributes.getNamedItem("data-"+ this.name).value,
                value = item.tagName === "INPUT" ? item.value : item.innerHTML;

            model = this.extract(model, key, value);
        }

        return model;
    };

    Extract.prototype.extract = function(model, key, value) {
        var keys = key.split(".");

        if(keys.length > 1) {
            var _key = keys.splice(0, 1);

            model[_key] = this.extract(model[_key] || {}, keys.join("."), value);
        }
        else {
            model[key] = value;
        }

        return model;
    };

    window.Extract = Extract;
})();
<commit_msg>Update: init to get and extract to put<commit_after>/**
 * Extract.js
 *
 * https://github.com/jostw/extract.js
 *
 * Copyright (c) 2014 jos
 * Licensed under the MIT license.
 */

"use strict";

(function() {
    var Extract = function(name) {
        this.name = name || "extract";
    };

    Extract.prototype.get = function(selector) {
        var query = document.querySelectorAll(selector +" [data-"+ this.name +"]"),

            i = 0,
            length = query.length,

            model = {};

        for( ; i < length; i++) {
            var item = query[i],

                key = item.attributes.getNamedItem("data-"+ this.name).value,
                value = item.tagName === "INPUT" ? item.value : item.innerHTML;

            model = this.put(model, key, value);
        }

        return model;
    };

    Extract.prototype.put = function(model, key, value) {
        var keys = key.split(".");

        if(keys.length > 1) {
            var _key = keys.splice(0, 1);

            model[_key] = this.put(model[_key] || {}, keys.join("."), value);
        }
        else {
            model[key] = value;
        }

        return model;
    };

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


<commit_before>/* Copyright 2020 Mozilla Foundation
 *
 * Licensed 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.
 */

import { Color } from "./color.js";
import { EventDispatcher } from "./event.js";
import { FullScreen } from "./fullscreen.js";
import { PDFObject } from "./pdf_object.js";
import { Thermometer } from "./thermometer.js";

const VIEWER_TYPE = "PDF.js";
const VIEWER_VARIATION = "Full";
const VIEWER_VERSION = 21.00720099;
const FORMS_VERSION = 21.00720099;

class App extends PDFObject {
  constructor(data) {
    super(data);

    this._constants = null;
    this._focusRect = true;
    this._fs = null;
    this._language = App._getLanguage(data.language);
    this._openInPlace = false;
    this._platform = App._getPlatform(data.platform);
    this._runtimeHighlight = false;
    this._runtimeHighlightColor = ["T"];
    this._thermometer = null;
    this._toolbar = false;

    this._document = data._document;
    this._proxyHandler = data.proxyHandler;
    this._objects = Object.create(null);
    this._eventDispatcher = new EventDispatcher(
      this._document,
      data.calculationOrder,
      this._objects
    );

    this._timeoutIds = new WeakMap();
    if (typeof FinalizationRegistry !== "undefined") {
      // About setTimeOut/setInterval return values (specs):
      //   The return value of this method must be held in a
      //   JavaScript variable.
      //   Otherwise, the timeout object is subject to garbage-collection,
      //   which would cause the clock to stop.
      this._timeoutIdsRegistry = new FinalizationRegistry(
        this._cleanTimeout.bind(this)
      );
    } else {
      this._timeoutIdsRegistry = null;
    }

    this._timeoutCallbackIds = new Map();
    this._timeoutCallbackId = 0;
    this._globalEval = data.globalEval;
    this._externalCall = data.externalCall;
    this._document = data._document;
  }

  // This function is called thanks to the proxy
  // when we call app['random_string'] to dispatch the event.
  _dispatchEvent(pdfEvent) {
    this._eventDispatcher.dispatch(pdfEvent);
  }

  _registerTimeoutCallback(cExpr) {
    const id = this._timeoutCallbackId++;
    this._timeoutCallbackIds.set(id, cExpr);
    return id;
  }

  _unregisterTimeoutCallback(id) {
    this._timeoutCallbackIds.delete(id);
  }

  _evalCallback({ callbackId, interval }) {
    const expr = this._timeoutCallbackIds.get(callbackId);
    if (!interval) {
      this._unregisterTimeoutCallback(callbackId);
    }

    if (expr) {
      this._globalEval(expr);
    }
  }

  _registerTimeout(callbackId, interval) {
    const timeout = Object.create(null);
    const id = { callbackId, interval };
    this._timeoutIds.set(timeout, id);
    this._timeoutIdsRegistry?.register(timeout, id);
    return timeout;
  }

  _unregisterTimeout(timeout) {
    this._timeoutIdsRegistry?.unregister(timeout);

    const data = this._timeoutIds.get(timeout);
    if (!data) {
      return;
    }

    this._timeoutIds.delete(timeout);
    this._cleanTimeout(data);
  }

  _cleanTimeout({ callbackId, interval }) {
    this._unregisterTimeoutCallback(callbackId);

    if (interval) {
      this._externalCall("clearInterval", [callbackId]);
    } else {
      this._externalCall("clearTimeout", [callbackId]);
    }
  }

  static _getPlatform(platform) {
    if (typeof platform === "string") {
      platform = platform.toLowerCase();
      if (platform.includes("win")) {
        return "WIN";
      } else if (platform.includes("mac")) {
        return "MAC";
      }
    }
    return "UNIX";
  }

  static _getLanguage(language) {
    const [main, sub] = language.toLowerCase().split(/[-_]/);
    switch (main) {
      case "zh":
        if (sub === "cn" || sub === "sg") {
          return "CHS";
        }
        return "CHT";
      case "da":
        return "DAN";
      case "de":
        return "DEU";
      case "es":
        return "ESP";
      case "fr":
        return "FRA";
      case "it":
        return "ITA";
      case "ko":
        return "KOR";
      case "ja":
        return "JPN";
      case "nl":
        return "NLD";
      case "no":
        return "NOR";
      case "pt":
        if (sub === "br") {
          return "PTB";
        }
        return "ENU";
      case "fi":
        return "SUO";
      case "SV":
        return "SVE";
      default:
        return "ENU";
    }
  }

  get activeDocs() {
    return [this._document.wrapped];
  }

  set activeDocs(_) {
    throw new Error("app.activeDocs is read-only");
  }

  get calculate() {
    return this._document.obj.calculate;
  }

  set calculate(calculate) {
    this._document.obj.calculate = calculate;
  }

  get constants() {
    if (!this._constants) {
      this._constants = Object.freeze({
        align: Object.freeze({
          left: 0,
          center: 1,
          right: 2,
          top: 3,
          bottom: 4,
        }),
      });
    }
    return this._constants;
  }

  set constants(_) {
    throw new Error("app.constants is read-only");
  }

  get focusRect() {
    return this._focusRect;
  }

  set focusRect(val) {
    /* TODO or not */
    this._focusRect = val;
  }

  get formsVersion() {
    return FORMS_VERSION;
  }

  set formsVersion(_) {
    throw new Error("app.formsVersion is read-only");
  }

  get fromPDFConverters() {
    return [];
  }

  set fromPDFConverters(_) {
    throw new Error("app.fromPDFConverters is read-only");
  }

  get fs() {
    if (this._fs === null) {
      this._fs = new Proxy(
        new FullScreen({ send: this._send }),
        this._proxyHandler
      );
    }
    return this._fs;
  }

  set fs(_) {
    throw new Error("app.fs is read-only");
  }

  get language() {
    return this._language;
  }

  set language(_) {
    throw new Error("app.language is read-only");
  }

  get media() {
    return undefined;
  }

  set media(_) {
    throw new Error("app.media is read-only");
  }

  get monitors() {
    return [];
  }

  set monitors(_) {
    throw new Error("app.monitors is read-only");
  }

  get numPlugins() {
    return 0;
  }

  set numPlugins(_) {
    throw new Error("app.numPlugins is read-only");
  }

  get openInPlace() {
    return this._openInPlace;
  }

  set openInPlace(val) {
    this._openInPlace = val;
    /* TODO */
  }

  get platform() {
    return this._platform;
  }

  set platform(_) {
    throw new Error("app.platform is read-only");
  }

  get plugins() {
    return [];
  }

  set plugins(_) {
    throw new Error("app.plugins is read-only");
  }

  get printColorProfiles() {
    return [];
  }

  set printColorProfiles(_) {
    throw new Error("app.printColorProfiles is read-only");
  }

  get printerNames() {
    return [];
  }

  set printerNames(_) {
    throw new Error("app.printerNames is read-only");
  }

  get runtimeHighlight() {
    return this._runtimeHighlight;
  }

  set runtimeHighlight(val) {
    this._runtimeHighlight = val;
    /* TODO */
  }

  get runtimeHighlightColor() {
    return this._runtimeHighlightColor;
  }

  set runtimeHighlightColor(val) {
    if (Color._isValidColor(val)) {
      this._runtimeHighlightColor = val;
      /* TODO */
    }
  }

  get thermometer() {
    if (this._thermometer === null) {
      this._thermometer = new Proxy(
        new Thermometer({ send: this._send }),
        this._proxyHandler
      );
    }
    return this._thermometer;
  }

  set thermometer(_) {
    throw new Error("app.thermometer is read-only");
  }

  get toolbar() {
    return this._toolbar;
  }

  set toolbar(val) {
    this._toolbar = val;
    /* TODO */
  }

  get toolbarHorizontal() {
    return this.toolbar;
  }

  set toolbarHorizontal(value) {
    /* has been deprecated and it's now equivalent to toolbar */
    this.toolbar = value;
  }

  get toolbarVertical() {
    return this.toolbar;
  }

  set toolbarVertical(value) {
    /* has been deprecated and it's now equivalent to toolbar */
    this.toolbar = value;
  }

  get viewerType() {
    return VIEWER_TYPE;
  }

  set viewerType(_) {
    throw new Error("app.viewerType is read-only");
  }

  get viewerVariation() {
    return VIEWER_VARIATION;
  }

  set viewerVariation(_) {
    throw new Error("app.viewerVariation is read-only");
  }

  get viewerVersion() {
    return VIEWER_VERSION;
  }

  set viewerVersion(_) {
    throw new Error("app.viewerVersion is read-only");
  }

  addMenuItem() {
    /* Not implemented */
  }

  addSubMenu() {
    /* Not implemented */
  }

  addToolButton() {
    /* Not implemented */
  }

  alert(
    cMsg,
    nIcon = 0,
    nType = 0,
    cTitle = "PDF.js",
    oDoc = null,
    oCheckbox = null
  ) {
    if (cMsg && typeof cMsg === "object") {
      nType = cMsg.nType;
      cMsg = cMsg.cMsg;
    }
    cMsg = (cMsg || "").toString();
    nType =
      typeof nType !== "number" || isNaN(nType) || nType < 0 || nType > 3
        ? 0
        : nType;
    if (nType >= 2) {
      return this._externalCall("confirm", [cMsg]) ? 4 : 3;
    }

    this._externalCall("alert", [cMsg]);
    return 1;
  }

  beep() {
    /* Not implemented */
  }

  beginPriv() {
    /* Not implemented */
  }

  browseForDoc() {
    /* Not implemented */
  }

  clearInterval(oInterval) {
    this._unregisterTimeout(oInterval);
  }

  clearTimeOut(oTime) {
    this._unregisterTimeout(oTime);
  }

  endPriv() {
    /* Not implemented */
  }

  execDialog() {
    /* Not implemented */
  }

  execMenuItem(item) {
    switch (item) {
      case "SaveAs":
      case "FirstPage":
      case "LastPage":
      case "NextPage":
      case "PrevPage":
      case "ZoomViewIn":
      case "ZoomViewOut":
        this._send({ command: item });
        break;
      case "FitPage":
        this._send({ command: "zoom", value: "page-fit" });
        break;
      case "Print":
        this._send({ command: "print" });
        break;
    }
  }

  getNthPlugInName() {
    /* Not implemented */
  }

  getPath() {
    /* Not implemented */
  }

  goBack() {
    /* TODO */
  }

  goForward() {
    /* TODO */
  }

  hideMenuItem() {
    /* Not implemented */
  }

  hideToolbarButton() {
    /* Not implemented */
  }

  launchURL() {
    /* Unsafe */
  }

  listMenuItems() {
    /* Not implemented */
  }

  listToolbarButtons() {
    /* Not implemented */
  }

  loadPolicyFile() {
    /* Not implemented */
  }

  mailGetAddrs() {
    /* Not implemented */
  }

  mailMsg() {
    /* TODO or not ? */
  }

  newDoc() {
    /* Not implemented */
  }

  newCollection() {
    /* Not implemented */
  }

  newFDF() {
    /* Not implemented */
  }

  openDoc() {
    /* Not implemented */
  }

  openFDF() {
    /* Not implemented */
  }

  popUpMenu() {
    /* Not implemented */
  }

  popUpMenuEx() {
    /* Not implemented */
  }

  removeToolButton() {
    /* Not implemented */
  }

  response(cQuestion, cTitle = "", cDefault = "", bPassword = "", cLabel = "") {
    if (cQuestion && typeof cQuestion === "object") {
      cDefault = cQuestion.cDefault;
      cQuestion = cQuestion.cQuestion;
    }
    cQuestion = (cQuestion || "").toString();
    cDefault = (cDefault || "").toString();
    return this._externalCall("prompt", [cQuestion, cDefault || ""]);
  }

  setInterval(cExpr, nMilliseconds = 0) {
    if (cExpr && typeof cExpr === "object") {
      nMilliseconds = cExpr.nMilliseconds || 0;
      cExpr = cExpr.cExpr;
    }

    if (typeof cExpr !== "string") {
      throw new TypeError("First argument of app.setInterval must be a string");
    }
    if (typeof nMilliseconds !== "number") {
      throw new TypeError(
        "Second argument of app.setInterval must be a number"
      );
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setInterval", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, true);
  }

  setTimeOut(cExpr, nMilliseconds = 0) {
    if (cExpr && typeof cExpr === "object") {
      nMilliseconds = cExpr.nMilliseconds || 0;
      cExpr = cExpr.cExpr;
    }

    if (typeof cExpr !== "string") {
      throw new TypeError("First argument of app.setTimeOut must be a string");
    }
    if (typeof nMilliseconds !== "number") {
      throw new TypeError("Second argument of app.setTimeOut must be a number");
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setTimeout", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, false);
  }

  trustedFunction() {
    /* Not implemented */
  }

  trustPropagatorFunction() {
    /* Not implemented */
  }
}

export { App };
<commit_msg>[JS] Remove duplicate `this._document` assignment in the `App`-class<commit_after>/* Copyright 2020 Mozilla Foundation
 *
 * Licensed 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.
 */

import { Color } from "./color.js";
import { EventDispatcher } from "./event.js";
import { FullScreen } from "./fullscreen.js";
import { PDFObject } from "./pdf_object.js";
import { Thermometer } from "./thermometer.js";

const VIEWER_TYPE = "PDF.js";
const VIEWER_VARIATION = "Full";
const VIEWER_VERSION = 21.00720099;
const FORMS_VERSION = 21.00720099;

class App extends PDFObject {
  constructor(data) {
    super(data);

    this._constants = null;
    this._focusRect = true;
    this._fs = null;
    this._language = App._getLanguage(data.language);
    this._openInPlace = false;
    this._platform = App._getPlatform(data.platform);
    this._runtimeHighlight = false;
    this._runtimeHighlightColor = ["T"];
    this._thermometer = null;
    this._toolbar = false;

    this._document = data._document;
    this._proxyHandler = data.proxyHandler;
    this._objects = Object.create(null);
    this._eventDispatcher = new EventDispatcher(
      this._document,
      data.calculationOrder,
      this._objects
    );

    this._timeoutIds = new WeakMap();
    if (typeof FinalizationRegistry !== "undefined") {
      // About setTimeOut/setInterval return values (specs):
      //   The return value of this method must be held in a
      //   JavaScript variable.
      //   Otherwise, the timeout object is subject to garbage-collection,
      //   which would cause the clock to stop.
      this._timeoutIdsRegistry = new FinalizationRegistry(
        this._cleanTimeout.bind(this)
      );
    } else {
      this._timeoutIdsRegistry = null;
    }

    this._timeoutCallbackIds = new Map();
    this._timeoutCallbackId = 0;
    this._globalEval = data.globalEval;
    this._externalCall = data.externalCall;
  }

  // This function is called thanks to the proxy
  // when we call app['random_string'] to dispatch the event.
  _dispatchEvent(pdfEvent) {
    this._eventDispatcher.dispatch(pdfEvent);
  }

  _registerTimeoutCallback(cExpr) {
    const id = this._timeoutCallbackId++;
    this._timeoutCallbackIds.set(id, cExpr);
    return id;
  }

  _unregisterTimeoutCallback(id) {
    this._timeoutCallbackIds.delete(id);
  }

  _evalCallback({ callbackId, interval }) {
    const expr = this._timeoutCallbackIds.get(callbackId);
    if (!interval) {
      this._unregisterTimeoutCallback(callbackId);
    }

    if (expr) {
      this._globalEval(expr);
    }
  }

  _registerTimeout(callbackId, interval) {
    const timeout = Object.create(null);
    const id = { callbackId, interval };
    this._timeoutIds.set(timeout, id);
    this._timeoutIdsRegistry?.register(timeout, id);
    return timeout;
  }

  _unregisterTimeout(timeout) {
    this._timeoutIdsRegistry?.unregister(timeout);

    const data = this._timeoutIds.get(timeout);
    if (!data) {
      return;
    }

    this._timeoutIds.delete(timeout);
    this._cleanTimeout(data);
  }

  _cleanTimeout({ callbackId, interval }) {
    this._unregisterTimeoutCallback(callbackId);

    if (interval) {
      this._externalCall("clearInterval", [callbackId]);
    } else {
      this._externalCall("clearTimeout", [callbackId]);
    }
  }

  static _getPlatform(platform) {
    if (typeof platform === "string") {
      platform = platform.toLowerCase();
      if (platform.includes("win")) {
        return "WIN";
      } else if (platform.includes("mac")) {
        return "MAC";
      }
    }
    return "UNIX";
  }

  static _getLanguage(language) {
    const [main, sub] = language.toLowerCase().split(/[-_]/);
    switch (main) {
      case "zh":
        if (sub === "cn" || sub === "sg") {
          return "CHS";
        }
        return "CHT";
      case "da":
        return "DAN";
      case "de":
        return "DEU";
      case "es":
        return "ESP";
      case "fr":
        return "FRA";
      case "it":
        return "ITA";
      case "ko":
        return "KOR";
      case "ja":
        return "JPN";
      case "nl":
        return "NLD";
      case "no":
        return "NOR";
      case "pt":
        if (sub === "br") {
          return "PTB";
        }
        return "ENU";
      case "fi":
        return "SUO";
      case "SV":
        return "SVE";
      default:
        return "ENU";
    }
  }

  get activeDocs() {
    return [this._document.wrapped];
  }

  set activeDocs(_) {
    throw new Error("app.activeDocs is read-only");
  }

  get calculate() {
    return this._document.obj.calculate;
  }

  set calculate(calculate) {
    this._document.obj.calculate = calculate;
  }

  get constants() {
    if (!this._constants) {
      this._constants = Object.freeze({
        align: Object.freeze({
          left: 0,
          center: 1,
          right: 2,
          top: 3,
          bottom: 4,
        }),
      });
    }
    return this._constants;
  }

  set constants(_) {
    throw new Error("app.constants is read-only");
  }

  get focusRect() {
    return this._focusRect;
  }

  set focusRect(val) {
    /* TODO or not */
    this._focusRect = val;
  }

  get formsVersion() {
    return FORMS_VERSION;
  }

  set formsVersion(_) {
    throw new Error("app.formsVersion is read-only");
  }

  get fromPDFConverters() {
    return [];
  }

  set fromPDFConverters(_) {
    throw new Error("app.fromPDFConverters is read-only");
  }

  get fs() {
    if (this._fs === null) {
      this._fs = new Proxy(
        new FullScreen({ send: this._send }),
        this._proxyHandler
      );
    }
    return this._fs;
  }

  set fs(_) {
    throw new Error("app.fs is read-only");
  }

  get language() {
    return this._language;
  }

  set language(_) {
    throw new Error("app.language is read-only");
  }

  get media() {
    return undefined;
  }

  set media(_) {
    throw new Error("app.media is read-only");
  }

  get monitors() {
    return [];
  }

  set monitors(_) {
    throw new Error("app.monitors is read-only");
  }

  get numPlugins() {
    return 0;
  }

  set numPlugins(_) {
    throw new Error("app.numPlugins is read-only");
  }

  get openInPlace() {
    return this._openInPlace;
  }

  set openInPlace(val) {
    this._openInPlace = val;
    /* TODO */
  }

  get platform() {
    return this._platform;
  }

  set platform(_) {
    throw new Error("app.platform is read-only");
  }

  get plugins() {
    return [];
  }

  set plugins(_) {
    throw new Error("app.plugins is read-only");
  }

  get printColorProfiles() {
    return [];
  }

  set printColorProfiles(_) {
    throw new Error("app.printColorProfiles is read-only");
  }

  get printerNames() {
    return [];
  }

  set printerNames(_) {
    throw new Error("app.printerNames is read-only");
  }

  get runtimeHighlight() {
    return this._runtimeHighlight;
  }

  set runtimeHighlight(val) {
    this._runtimeHighlight = val;
    /* TODO */
  }

  get runtimeHighlightColor() {
    return this._runtimeHighlightColor;
  }

  set runtimeHighlightColor(val) {
    if (Color._isValidColor(val)) {
      this._runtimeHighlightColor = val;
      /* TODO */
    }
  }

  get thermometer() {
    if (this._thermometer === null) {
      this._thermometer = new Proxy(
        new Thermometer({ send: this._send }),
        this._proxyHandler
      );
    }
    return this._thermometer;
  }

  set thermometer(_) {
    throw new Error("app.thermometer is read-only");
  }

  get toolbar() {
    return this._toolbar;
  }

  set toolbar(val) {
    this._toolbar = val;
    /* TODO */
  }

  get toolbarHorizontal() {
    return this.toolbar;
  }

  set toolbarHorizontal(value) {
    /* has been deprecated and it's now equivalent to toolbar */
    this.toolbar = value;
  }

  get toolbarVertical() {
    return this.toolbar;
  }

  set toolbarVertical(value) {
    /* has been deprecated and it's now equivalent to toolbar */
    this.toolbar = value;
  }

  get viewerType() {
    return VIEWER_TYPE;
  }

  set viewerType(_) {
    throw new Error("app.viewerType is read-only");
  }

  get viewerVariation() {
    return VIEWER_VARIATION;
  }

  set viewerVariation(_) {
    throw new Error("app.viewerVariation is read-only");
  }

  get viewerVersion() {
    return VIEWER_VERSION;
  }

  set viewerVersion(_) {
    throw new Error("app.viewerVersion is read-only");
  }

  addMenuItem() {
    /* Not implemented */
  }

  addSubMenu() {
    /* Not implemented */
  }

  addToolButton() {
    /* Not implemented */
  }

  alert(
    cMsg,
    nIcon = 0,
    nType = 0,
    cTitle = "PDF.js",
    oDoc = null,
    oCheckbox = null
  ) {
    if (cMsg && typeof cMsg === "object") {
      nType = cMsg.nType;
      cMsg = cMsg.cMsg;
    }
    cMsg = (cMsg || "").toString();
    nType =
      typeof nType !== "number" || isNaN(nType) || nType < 0 || nType > 3
        ? 0
        : nType;
    if (nType >= 2) {
      return this._externalCall("confirm", [cMsg]) ? 4 : 3;
    }

    this._externalCall("alert", [cMsg]);
    return 1;
  }

  beep() {
    /* Not implemented */
  }

  beginPriv() {
    /* Not implemented */
  }

  browseForDoc() {
    /* Not implemented */
  }

  clearInterval(oInterval) {
    this._unregisterTimeout(oInterval);
  }

  clearTimeOut(oTime) {
    this._unregisterTimeout(oTime);
  }

  endPriv() {
    /* Not implemented */
  }

  execDialog() {
    /* Not implemented */
  }

  execMenuItem(item) {
    switch (item) {
      case "SaveAs":
      case "FirstPage":
      case "LastPage":
      case "NextPage":
      case "PrevPage":
      case "ZoomViewIn":
      case "ZoomViewOut":
        this._send({ command: item });
        break;
      case "FitPage":
        this._send({ command: "zoom", value: "page-fit" });
        break;
      case "Print":
        this._send({ command: "print" });
        break;
    }
  }

  getNthPlugInName() {
    /* Not implemented */
  }

  getPath() {
    /* Not implemented */
  }

  goBack() {
    /* TODO */
  }

  goForward() {
    /* TODO */
  }

  hideMenuItem() {
    /* Not implemented */
  }

  hideToolbarButton() {
    /* Not implemented */
  }

  launchURL() {
    /* Unsafe */
  }

  listMenuItems() {
    /* Not implemented */
  }

  listToolbarButtons() {
    /* Not implemented */
  }

  loadPolicyFile() {
    /* Not implemented */
  }

  mailGetAddrs() {
    /* Not implemented */
  }

  mailMsg() {
    /* TODO or not ? */
  }

  newDoc() {
    /* Not implemented */
  }

  newCollection() {
    /* Not implemented */
  }

  newFDF() {
    /* Not implemented */
  }

  openDoc() {
    /* Not implemented */
  }

  openFDF() {
    /* Not implemented */
  }

  popUpMenu() {
    /* Not implemented */
  }

  popUpMenuEx() {
    /* Not implemented */
  }

  removeToolButton() {
    /* Not implemented */
  }

  response(cQuestion, cTitle = "", cDefault = "", bPassword = "", cLabel = "") {
    if (cQuestion && typeof cQuestion === "object") {
      cDefault = cQuestion.cDefault;
      cQuestion = cQuestion.cQuestion;
    }
    cQuestion = (cQuestion || "").toString();
    cDefault = (cDefault || "").toString();
    return this._externalCall("prompt", [cQuestion, cDefault || ""]);
  }

  setInterval(cExpr, nMilliseconds = 0) {
    if (cExpr && typeof cExpr === "object") {
      nMilliseconds = cExpr.nMilliseconds || 0;
      cExpr = cExpr.cExpr;
    }

    if (typeof cExpr !== "string") {
      throw new TypeError("First argument of app.setInterval must be a string");
    }
    if (typeof nMilliseconds !== "number") {
      throw new TypeError(
        "Second argument of app.setInterval must be a number"
      );
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setInterval", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, true);
  }

  setTimeOut(cExpr, nMilliseconds = 0) {
    if (cExpr && typeof cExpr === "object") {
      nMilliseconds = cExpr.nMilliseconds || 0;
      cExpr = cExpr.cExpr;
    }

    if (typeof cExpr !== "string") {
      throw new TypeError("First argument of app.setTimeOut must be a string");
    }
    if (typeof nMilliseconds !== "number") {
      throw new TypeError("Second argument of app.setTimeOut must be a number");
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setTimeout", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, false);
  }

  trustedFunction() {
    /* Not implemented */
  }

  trustPropagatorFunction() {
    /* Not implemented */
  }
}

export { App };
<|endoftext|>


<commit_before>/*
 * grunt-shopify-theme-settings
 * https://github.com/discolabs/grunt-shopify-theme-settings
 *
 * Copyright (c) 2014 Gavin Ballard
 * Licensed under the MIT license.
 */

'use strict';
var swig = require('swig');
var tidy = require('htmltidy').tidy;

module.exports = function(grunt) {

  grunt.registerMultiTask('shopify_theme_settings', 'Grunt plugin to build a settings.html file for Shopify themes.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      templates: [],
      tidyOptions: {
        docType: 'strict',
        outputXhtml: true,
        indent: true,
        indentSpaces: 4,
        wrap: 0,
        showBodyOnly: true,
        dropEmptyElements: false
      }
    });

    // Mark this task as asynchronous.
    var done = this.async();

    // Iterate over all specified file targets.
    this.files.forEach(function(f) {

      // Test each source YAML file for existence, then reduce the parsed YAML into a single sections object.
      var sections = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).reduce(function(sections, filepath) {
        // Parse source file.
        var parsed = grunt.file.readYAML(filepath);

        // Add the sections from the parsed source file to our existing sections.
        for(var key in parsed) {
          if(parsed.hasOwnProperty(key)) {
            sections[key] = parsed[key];
          }
        }

        return sections;
      }, {});

      // If we have a specified include path, use a specialised filesystem loader for Swig templates that tries to load
      // from our specified include directory first, then falls back to the default loader.
      if(options.templates.length) {
        options.templates.push('');
        swig.setDefaults({ loader: fsMultipleDirectoryLoader(options.templates) });
      }

      // Compile the template using Swig.
      var settingsTemplate = swig.compileFile(__dirname + '/templates/settings.html');

      // Execute (render) our compiled template.
      var output = settingsTemplate({
        sections: sections
      });

      // Tidy using HTMLTidy.
      tidy(output, options.tidyOptions, function(err, tidiedOutput) {
        // Write the destination file.
        grunt.file.write(f.dest, tidiedOutput);

        // Print a success message.
        grunt.log.writeln('File "' + f.dest + '" created.');

        // Mark asynchronous task as done.
        done();
      });
    });
  });

  /**
   * Define a simple customer filesystem loader for Swig templates that can resolve from multiple templates directories
   * in order of precedence.
   *
   * See: http://paularmstrong.github.io/swig/docs/loaders/#custom
   *
   * @param basepaths
   * @param encoding
   * @returns {{}}
   */
  function fsMultipleDirectoryLoader(basepaths, encoding) {
    var ret = {}, loaders;

    // Ensure we have something in our basepaths, and that it's an array.
    if(!basepaths || !basepaths.length) {
      basepaths = [''];
    }

    // Create a loader for each basepath.
    loaders = basepaths.map(function(basepath) {
      return swig.loaders.fs(basepath, encoding);
    });

    /**
     * Resolve to a path for the given template.
     *
     * @param to
     * @param from
     * @returns {*}
     */
    ret.resolve = function(to, from) {
      var candidates = loaders.map(function(loader) {
        return loader.resolve(to, from);
      });

      // Return the first candidate that exists.
      for(var i = 0, l = candidates.length; i < l; i++) {
        if(grunt.file.isFile(candidates[i])) {
          return candidates[i];
        }
      }
    };

    // Pass the template loader load() method off to the default Swig filesystem loader load() method.
    ret.load = loaders[0].load;

    return ret;
  }

};
<commit_msg>Fix for major bug with custom template loading.<commit_after>/*
 * grunt-shopify-theme-settings
 * https://github.com/discolabs/grunt-shopify-theme-settings
 *
 * Copyright (c) 2014 Gavin Ballard
 * Licensed under the MIT license.
 */

'use strict';
var swig = require('swig');
var tidy = require('htmltidy').tidy;
var fs = require('fs');

module.exports = function(grunt) {

  grunt.registerMultiTask('shopify_theme_settings', 'Grunt plugin to build a settings.html file for Shopify themes.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      templates: [],
      tidyOptions: {
        docType: 'strict',
        outputXhtml: true,
        indent: true,
        indentSpaces: 4,
        wrap: 0,
        showBodyOnly: true,
        dropEmptyElements: false
      }
    });

    // Mark this task as asynchronous.
    var done = this.async();

    // Iterate over all specified file targets.
    this.files.forEach(function(f) {

      // Test each source YAML file for existence, then reduce the parsed YAML into a single sections object.
      var sections = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).reduce(function(sections, filepath) {
        // Parse source file.
        var parsed = grunt.file.readYAML(filepath);

        // Add the sections from the parsed source file to our existing sections.
        for(var key in parsed) {
          if(parsed.hasOwnProperty(key)) {
            sections[key] = parsed[key];
          }
        }

        return sections;
      }, {});

      // If we have a specified include path, use a specialised filesystem loader for Swig templates that tries to load
      // from our specified include directory first, then falls back to the default loader.
      if(options.templates.length) {
        options.templates.push('');
        swig.setDefaults({ loader: fsMultipleDirectoryLoader(options.templates) });
      }

      // Compile the template using Swig.
      var settingsTemplate = swig.compileFile(__dirname + '/templates/settings.html');

      // Execute (render) our compiled template.
      var output = settingsTemplate({
        sections: sections
      });

      // Tidy using HTMLTidy.
      tidy(output, options.tidyOptions, function(err, tidiedOutput) {
        // Write the destination file.
        grunt.file.write(f.dest, tidiedOutput);

        // Print a success message.
        grunt.log.writeln('File "' + f.dest + '" created.');

        // Mark asynchronous task as done.
        done();
      });
    });
  });

  /**
   * Define a simple customer filesystem loader for Swig templates that can resolve from multiple templates directories
   * in order of precedence.
   *
   * See: http://paularmstrong.github.io/swig/docs/loaders/#custom
   *
   * @param basepaths
   * @param encoding
   * @returns {{}}
   */
  function fsMultipleDirectoryLoader(basepaths, encoding) {
    var ret = {}, loaders;

    // Ensure we have an encoding defined.
    encoding = encoding || 'utf8';

    // Ensure we have something in our basepaths, and that it's an array.
    if(!basepaths || !basepaths.length) {
      basepaths = [''];
    }

    // Create a loader for each basepath.
    loaders = basepaths.map(function(basepath) {
      return swig.loaders.fs(basepath, encoding);
    });

    /**
     * Resolve to a path for the given template.
     *
     * @param to
     * @param from
     * @returns {*}
     */
    ret.resolve = function(to, from) {
      var candidates = loaders.map(function(loader) {
        return loader.resolve(to, from);
      });

      // Return the first candidate that exists.
      for(var i = 0, l = candidates.length; i < l; i++) {
        if(grunt.file.isFile(candidates[i])) {
          return candidates[i];
        }
      }
    };

    /**
     * Load a given template.
     *
     * This loader is identical to the default filesystem loader, but is required so that our custom resolve() method
     * can be used within it.
     *
     * See https://github.com/paularmstrong/swig/blob/master/lib/loaders/filesystem.js.
     *
     * @param identifier
     * @param cb
     * @returns {*}
     */
    ret.load = function(identifier, cb) {
      if (!fs || (cb && !fs.readFile) || !fs.readFileSync) {
        throw new Error('Unable to find file ' + identifier + ' because there is no filesystem to read from.');
      }

      identifier = ret.resolve(identifier);

      if(cb) {
        fs.readFile(identifier, encoding, cb);
        return;
      }
      return fs.readFileSync(identifier, encoding);
    };

    return ret;
  }

};
<|endoftext|>


<commit_before>$( function() {
    $("#erase_item").click(function () {
        $("#results").html('');
        $("#item").val('').focus();
        window.history.replaceState({}, "MH Hunt Helper", "converter.php");
    });

    searchItems('all', firstLoad);

    function searchItems(item_id, callback) {
        if (item_id !== 'all') {
            $("#loader").css( "display", "block" );
            // Every time we search for a item (on reload or ajax) set a history of it.
            window.history.replaceState({}, "MH Hunt Helper", "converter.php?item=" + item_id);
        }

        $.ajax({
            url: "searchByItem.php",
            method: "GET",
            data: {
                item_id: item_id,
                item_type: "convertible"
            }
        })
        .done(function( data ) {
            callback( JSON.parse(data));
        });
    }

    function firstLoad(items) {
        // Check and search for previous item (done on reload of whole page)
        var previous_item_id = $("#prev_item").val();
        if (previous_item_id) {
            var previous_item_name = '';
            for (var i = 0; i < items.length; i++) {
                if (items[i].id == previous_item_id) {
                    previous_item_name = items[i].value;
                    $("#item").val(previous_item_name);
                    break;
                }
            }
            searchItems($("#prev_item").val(), renderResultsTable);
        }

        // set autocomplete
        addAutocomplete(items);
    }

    function addAutocomplete(items) {
        $('#item').autocomplete({
            source: function(request, response) {
                var results = $.ui.autocomplete.filter(items, request.term);
                response(results.slice(0, 10));
            },
            delay: 0,
            select: function( event, ui ) {
                searchItems(ui.item.id, renderResultsTable);
            }
        });

        // Fix for double click on IOS
        if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
            $('#item').autocomplete('widget').off('mouseenter');
        }
    }

    function renderResultsTable(data) {
        var final_html = '

Item	Average Qty	Chance for any	Min-Max Qty

';

        var all_stages = '';
        let total_seen = 'Did not find this convertible';
        data.forEach(function(row) {
            total_seen = row.total + ' convertibles. (Opened single ' + row.single_opens + ')';
            final_html += '
' + row.item + '	';
            final_html += parseFloat((row.total_items / row.total).toPrecision(3)) + '	';
            if (row.single_opens == 0) {
                final_html += 'N/A' + '	';
            } else {
                final_html += parseFloat((row.times_with_any / row.single_opens * 100).toPrecision(3)) + '%	';
            }
            final_html += row.min_item_quantity + '-' + row.max_item_quantity + '
';
        });
        final_html += '

';

        total_seen = '
' + total_seen + '
';
        $('#results_total').html(total_seen);

        $("#results").html(final_html);
        $('#results_table').DataTable( {
            "paging":   false,
            "searching": false,
            "info": false,
            "order": [[1, 'desc']]
        });

        var table = $('#results_table').DataTable();
        table.columns().iterator( 'column', function (ctx, idx) {
            $( table.column(idx).header() ).append('');
        });

        $("#loader").css( "display", "none" );
    }
});
<commit_msg>rephrased opened single<commit_after>$( function() {
    $("#erase_item").click(function () {
        $("#results").html('');
        $("#item").val('').focus();
        window.history.replaceState({}, "MH Hunt Helper", "converter.php");
    });

    searchItems('all', firstLoad);

    function searchItems(item_id, callback) {
        if (item_id !== 'all') {
            $("#loader").css( "display", "block" );
            // Every time we search for a item (on reload or ajax) set a history of it.
            window.history.replaceState({}, "MH Hunt Helper", "converter.php?item=" + item_id);
        }

        $.ajax({
            url: "searchByItem.php",
            method: "GET",
            data: {
                item_id: item_id,
                item_type: "convertible"
            }
        })
        .done(function( data ) {
            callback( JSON.parse(data));
        });
    }

    function firstLoad(items) {
        // Check and search for previous item (done on reload of whole page)
        var previous_item_id = $("#prev_item").val();
        if (previous_item_id) {
            var previous_item_name = '';
            for (var i = 0; i < items.length; i++) {
                if (items[i].id == previous_item_id) {
                    previous_item_name = items[i].value;
                    $("#item").val(previous_item_name);
                    break;
                }
            }
            searchItems($("#prev_item").val(), renderResultsTable);
        }

        // set autocomplete
        addAutocomplete(items);
    }

    function addAutocomplete(items) {
        $('#item').autocomplete({
            source: function(request, response) {
                var results = $.ui.autocomplete.filter(items, request.term);
                response(results.slice(0, 10));
            },
            delay: 0,
            select: function( event, ui ) {
                searchItems(ui.item.id, renderResultsTable);
            }
        });

        // Fix for double click on IOS
        if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
            $('#item').autocomplete('widget').off('mouseenter');
        }
    }

    function renderResultsTable(data) {
        var final_html = '

Item	Average Qty	Chance for any	Min-Max Qty

';

        var all_stages = '';
        let total_seen = 'Did not find this convertible';
        data.forEach(function(row) {
            total_seen = row.total + ' convertibles. (' + row.single_opens + ' opened single)';
            final_html += '
' + row.item + '	';
            final_html += parseFloat((row.total_items / row.total).toPrecision(3)) + '	';
            if (row.single_opens == 0) {
                final_html += 'N/A' + '	';
            } else {
                final_html += parseFloat((row.times_with_any / row.single_opens * 100).toPrecision(3)) + '%	';
            }
            final_html += row.min_item_quantity + '-' + row.max_item_quantity + '
';
        });
        final_html += '

';

        total_seen = '
' + total_seen + '
';
        $('#results_total').html(total_seen);

        $("#results").html(final_html);
        $('#results_table').DataTable( {
            "paging":   false,
            "searching": false,
            "info": false,
            "order": [[1, 'desc']]
        });

        var table = $('#results_table').DataTable();
        table.columns().iterator( 'column', function (ctx, idx) {
            $( table.column(idx).header() ).append('');
        });

        $("#loader").css( "display", "none" );
    }
});
<|endoftext|>


<commit_before>'use strict';

module.exports = function(crowi, app) {
  var debug = require('debug')('crowi:crowi:express-init')
    , express        = require('express')
    , bodyParser     = require('body-parser')
    , cookieParser   = require('cookie-parser')
    , methodOverride = require('method-override')
    , session        = require('express-session')
    , basicAuth      = require('basic-auth-connect')
    , flash          = require('connect-flash')
    , cons           = require('consolidate')
    , swig           = require('swig')
    , i18next        = require('i18next')
    , i18nFsBackend  = require('i18next-node-fs-backend')
    , i18nSprintf    = require('i18next-sprintf-postprocessor')
    , i18nMiddleware = require('i18next-express-middleware')
    , i18nUserSettingDetector  = require('../util/i18nUserSettingDetector')
    , env            = crowi.node_env
    , middleware     = require('../util/middlewares')

    , User = crowi.model('User')
    ;

  var lngDetector = new i18nMiddleware.LanguageDetector();
  lngDetector.addDetector(i18nUserSettingDetector);

  i18next
    .use(lngDetector)
    .use(i18nFsBackend)
    .use(i18nSprintf)
    .init({
      debug: (crowi.node_env === 'development'),
      fallbackLng: [User.LANG_EN_US],
      whitelist: Object.keys(User.getLanguageLabels()).map((k) => User[k]),
      backend: {
        loadPath: 'locales/{{lng}}/translation.json'
      },
      detection: {
        order: ['userSettingDetector', 'header', 'navigator'],
      },
      overloadTranslationOptionHandler: i18nSprintf.overloadTranslationOptionHandler
    });

  app.use(function(req, res, next) {
    var now = new Date()
      , baseUrl
      , config = crowi.getConfig()
      , tzoffset = -(config.crowi['app:timezone'] || 9) * 60 // for datez
      , Page = crowi.model('Page')
      , User = crowi.model('User')
      , Config = crowi.model('Config')
      ;

    app.set('tzoffset', tzoffset);

    req.config = config;
    req.csrfToken = null;

    config.crowi['app:url'] = baseUrl = (req.headers['x-forwarded-proto'] == 'https' ? 'https' : req.protocol) + '://' + req.get('host');

    res.locals.req      = req;
    res.locals.baseUrl  = baseUrl;
    res.locals.config   = config;
    res.locals.env      = env;
    res.locals.now      = now;
    res.locals.tzoffset = tzoffset;
    res.locals.consts   = {
        pageGrants: Page.getGrantLabels(),
        userStatus: User.getUserStatusLabels(),
        language:   User.getLanguageLabels(),
        registrationMode: Config.getRegistrationModeLabels(),
    };

    next();
  });

  // Set basic auth middleware
  app.use(function(req, res, next) {
    var config = crowi.getConfig();

    if (config.crowi['security:basicName'] && config.crowi['security:basicSecret']) {
      return basicAuth(
        config.crowi['security:basicName'],
        config.crowi['security:basicSecret'])(req, res, next);
    } else {
      next();
    }
  });

  app.set('port', crowi.port);
  app.use(express.static(crowi.publicDir));
  app.engine('html', cons.swig);
  app.set('view cache', false);
  app.set('view engine', 'html');
  app.set('views', crowi.viewsDir);
  app.use(methodOverride());
  app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
  app.use(bodyParser.json({limit: '50mb'}));
  app.use(cookieParser());
  app.use(session(crowi.sessionConfig));
  app.use(flash());

  app.use(middleware.swigFilters(app, swig));
  app.use(middleware.swigFunctions(crowi, app));

  app.use(middleware.loginChecker(crowi, app));

  app.use(i18nMiddleware.handle(i18next));
};
<commit_msg>Fix: locales path<commit_after>'use strict';

module.exports = function(crowi, app) {
  var debug = require('debug')('crowi:crowi:express-init')
    , express        = require('express')
    , bodyParser     = require('body-parser')
    , cookieParser   = require('cookie-parser')
    , methodOverride = require('method-override')
    , session        = require('express-session')
    , basicAuth      = require('basic-auth-connect')
    , flash          = require('connect-flash')
    , cons           = require('consolidate')
    , swig           = require('swig')
    , i18next        = require('i18next')
    , i18nFsBackend  = require('i18next-node-fs-backend')
    , i18nSprintf    = require('i18next-sprintf-postprocessor')
    , i18nMiddleware = require('i18next-express-middleware')
    , i18nUserSettingDetector  = require('../util/i18nUserSettingDetector')
    , env            = crowi.node_env
    , middleware     = require('../util/middlewares')

    , User = crowi.model('User')
    ;

  var lngDetector = new i18nMiddleware.LanguageDetector();
  lngDetector.addDetector(i18nUserSettingDetector);

  i18next
    .use(lngDetector)
    .use(i18nFsBackend)
    .use(i18nSprintf)
    .init({
      debug: (crowi.node_env === 'development'),
      fallbackLng: [User.LANG_EN_US],
      whitelist: Object.keys(User.getLanguageLabels()).map((k) => User[k]),
      backend: {
        loadPath: crowi.localeDir + '{{lng}}/translation.json'
      },
      detection: {
        order: ['userSettingDetector', 'header', 'navigator'],
      },
      overloadTranslationOptionHandler: i18nSprintf.overloadTranslationOptionHandler
    });

  app.use(function(req, res, next) {
    var now = new Date()
      , baseUrl
      , config = crowi.getConfig()
      , tzoffset = -(config.crowi['app:timezone'] || 9) * 60 // for datez
      , Page = crowi.model('Page')
      , User = crowi.model('User')
      , Config = crowi.model('Config')
      ;

    app.set('tzoffset', tzoffset);

    req.config = config;
    req.csrfToken = null;

    config.crowi['app:url'] = baseUrl = (req.headers['x-forwarded-proto'] == 'https' ? 'https' : req.protocol) + '://' + req.get('host');

    res.locals.req      = req;
    res.locals.baseUrl  = baseUrl;
    res.locals.config   = config;
    res.locals.env      = env;
    res.locals.now      = now;
    res.locals.tzoffset = tzoffset;
    res.locals.consts   = {
        pageGrants: Page.getGrantLabels(),
        userStatus: User.getUserStatusLabels(),
        language:   User.getLanguageLabels(),
        registrationMode: Config.getRegistrationModeLabels(),
    };

    next();
  });

  // Set basic auth middleware
  app.use(function(req, res, next) {
    var config = crowi.getConfig();

    if (config.crowi['security:basicName'] && config.crowi['security:basicSecret']) {
      return basicAuth(
        config.crowi['security:basicName'],
        config.crowi['security:basicSecret'])(req, res, next);
    } else {
      next();
    }
  });

  app.set('port', crowi.port);
  app.use(express.static(crowi.publicDir));
  app.engine('html', cons.swig);
  app.set('view cache', false);
  app.set('view engine', 'html');
  app.set('views', crowi.viewsDir);
  app.use(methodOverride());
  app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
  app.use(bodyParser.json({limit: '50mb'}));
  app.use(cookieParser());
  app.use(session(crowi.sessionConfig));
  app.use(flash());

  app.use(middleware.swigFilters(app, swig));
  app.use(middleware.swigFunctions(crowi, app));

  app.use(middleware.loginChecker(crowi, app));

  app.use(i18nMiddleware.handle(i18next));
};
<|endoftext|>


<commit_before>import React from 'react';
import {Range} from 'atom';
import PropTypes from 'prop-types';
import {EndpointPropType} from '../prop-types';
import Decoration from '../atom/decoration';
import Marker from '../atom/marker';
import ReviewsItem from '../items/reviews-item';
import {addEvent} from '../reporter-proxy';

export default class CommentGutterDecorationController extends React.Component {

  static propTypes = {
    commentRow: PropTypes.number.isRequired,
    threadId: PropTypes.string.isRequired,
    extraClasses: PropTypes.array,

    workspace: PropTypes.object.isRequired,
    endpoint: EndpointPropType.isRequired,
    owner: PropTypes.string.isRequired,
    repo: PropTypes.string.isRequired,
    number: PropTypes.number.isRequired,
    workdir: PropTypes.string.isRequired,
    editor: PropTypes.object,
  };

  static defaultProps = {
    extraClasses: [],
  }

  render() {
    const range = Range.fromObject([[this.props.commentRow, 0], [this.props.commentRow, 0]]);
    return (
      <Marker
        key={`github-comment-gutter-decoration-${this.props.threadId}`}
        editor={this.props.editor}
        bufferRange={range}>
        <Decoration
          editor={this.props.editor}
          type="gutter"
          gutterName="github-comment-icon"
          className={`github-editorCommentGutterIcon ${this.props.extraClasses.join(' ')}`}
          omitEmptyLastRow={false}>
          <button className="icon icon-comment" onClick={() => this.openReviewThread(this.props.threadId)} />
        </Decoration>
      </Marker>
    );
  }

  async openReviewThread(threadId) {
    const uri = ReviewsItem.buildURI(
      this.props.endpoint.getHost(),
      this.props.owner,
      this.props.repo,
      this.props.number,
      this.props.workdir,
    );
    const reviewsItem = await this.props.workspace.open(uri, {searchAllPanes: true});
    reviewsItem.jumpToThread(threadId);
    addEvent('open-review-thread', {package: 'github'});
  }

}
<commit_msg>be more specific about where the event is firing from<commit_after>import React from 'react';
import {Range} from 'atom';
import PropTypes from 'prop-types';
import {EndpointPropType} from '../prop-types';
import Decoration from '../atom/decoration';
import Marker from '../atom/marker';
import ReviewsItem from '../items/reviews-item';
import {addEvent} from '../reporter-proxy';

export default class CommentGutterDecorationController extends React.Component {

  static propTypes = {
    commentRow: PropTypes.number.isRequired,
    threadId: PropTypes.string.isRequired,
    extraClasses: PropTypes.array,

    workspace: PropTypes.object.isRequired,
    endpoint: EndpointPropType.isRequired,
    owner: PropTypes.string.isRequired,
    repo: PropTypes.string.isRequired,
    number: PropTypes.number.isRequired,
    workdir: PropTypes.string.isRequired,
    editor: PropTypes.object,
  };

  static defaultProps = {
    extraClasses: [],
  }

  render() {
    const range = Range.fromObject([[this.props.commentRow, 0], [this.props.commentRow, 0]]);
    return (
      <Marker
        key={`github-comment-gutter-decoration-${this.props.threadId}`}
        editor={this.props.editor}
        bufferRange={range}>
        <Decoration
          editor={this.props.editor}
          type="gutter"
          gutterName="github-comment-icon"
          className={`github-editorCommentGutterIcon ${this.props.extraClasses.join(' ')}`}
          omitEmptyLastRow={false}>
          <button className="icon icon-comment" onClick={() => this.openReviewThread(this.props.threadId)} />
        </Decoration>
      </Marker>
    );
  }

  async openReviewThread(threadId) {
    const uri = ReviewsItem.buildURI(
      this.props.endpoint.getHost(),
      this.props.owner,
      this.props.repo,
      this.props.number,
      this.props.workdir,
    );
    const reviewsItem = await this.props.workspace.open(uri, {searchAllPanes: true});
    reviewsItem.jumpToThread(threadId);
    addEvent('open-review-thread', {package: 'github', from: this.constructor.name});
  }

}
<|endoftext|>


<commit_before>// secure env vars not available in pull requests
if (process.env.TRAVIS_SECURE_ENV_VARS == 'false') return

var should = require("should")
  , dynamo = require("../")
  , region = "us-east-1"
  , name   = "jed_dynamo-client_test"

describe("dynamo", function() {
  it("starting tests at " + JSON.stringify(new Date))

  describe("'CreateTable'", function() {
    it("should create a table", function(done) {
      var db = dynamo.createClient(region)
      db.request("CreateTable", {
        TableName: name,
        KeySchema: {
          HashKeyElement: {
            AttributeName: "id",
            AttributeType: "N"
          }
        },
        ProvisionedThroughput: {
          ReadCapacityUnits: 3,
          WriteCapacityUnits: 5
        }
      }, function(err, data) {
        if (err && err.name == "ResourceInUseException") err = null

        done(err)
      })
    })
  })

  describe("'DescribeTable'", function() {
    it("should return table information", function describe(done) {
      var db = dynamo.createClient(region)
      db.request("DescribeTable", {TableName: name}, function(err, data) {
        if (err) done(err)

        else if (data.Table.TableStatus.slice(-3) != "ING") done()

        else setTimeout(describe, 5000, done)
      })
    })
  })
})
<commit_msg>Ensure the table is not in the middle of being deleted<commit_after>// secure env vars not available in pull requests
if (process.env.TRAVIS_SECURE_ENV_VARS == 'false') return

var should = require("should")
  , dynamo = require("../")
  , region = "us-east-1"
  , name   = "jed_dynamo-client_test"

describe("dynamo", function() {
  it("starting tests at " + JSON.stringify(new Date))

  describe("'DescribeTable'", function() {
    it("should ensure the table is not being deleted", function describe(done) {
      var db = dynamo.createClient(region)
      db.request("DescribeTable", {TableName: name}, function(err, data) {
        if (err && err.name == "ResourceNotFoundException") done()

        else if (err) done(err)

        else if (data.Table.TableStatus == "DELETING") setTimeout(describe, 5000, done)

        else done()
      })
    })
  })

  describe("'CreateTable'", function() {
    it("should create a table", function(done) {
      var db = dynamo.createClient(region)
      db.request("CreateTable", {
        TableName: name,
        KeySchema: {
          HashKeyElement: {
            AttributeName: "id",
            AttributeType: "N"
          }
        },
        ProvisionedThroughput: {
          ReadCapacityUnits: 3,
          WriteCapacityUnits: 5
        }
      }, function(err, data) {
        if (err && err.name == "ResourceInUseException") err = null

        done(err)
      })
    })
  })

  describe("'DescribeTable'", function() {
    it("should return table information", function describe(done) {
      var db = dynamo.createClient(region)
      db.request("DescribeTable", {TableName: name}, function(err, data) {
        if (err) done(err)

        else if (data.Table.TableStatus.slice(-3) != "ING") done()

        else setTimeout(describe, 5000, done)
      })
    })
  })
})
<|endoftext|>


<commit_before><commit_msg>Enable use of chai-as-promised in tests<commit_after><|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var request = require('request');
var fs = require('fs');
var jsdom = require("jsdom");
var Promise = require('bluebird');
var path = require('path');
var url = require('url');

Promise.promisifyAll(request);
Promise.promisifyAll(fs);
Promise.promisifyAll(jsdom);

var app = express();

var results = {};

app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    resave: false,
    saveUninitialized: true,
    secret: 'keyboard cat',
    cookie: {
        maxAge: 300000
    }
}));

app.use(function(req, res, next){
    console.log(req.session);
    console.log(req.sessionID);
    next();
});

app.use(express.static(__dirname + '/public'));
app.post('/grade', function(req, res){
    results[req.sessionID] = {stauts: 'processing'};
    res.status(200);
    res.redirect('/result');
    res.end();
    var files = [];
    request.getAsync(req.body)
    .then(function(result){
        var body = result[1];
        files.push({
            name: 'index.html',
            body: body
        });
        return jsdom.envAsync(body);
    })
    .then(function(window){
        var static_data_list = [];
        var links = window.document.getElementsByTagName('link');
        for(var i = 0; i < links.length; i++){
            var href = links[i].getAttribute('href');
            var rel = links[i].getAttribute('rel');
            if(href && rel == 'stylesheet'){
                static_data_list.push(href);
            }
        }
        var scripts = window.document.getElementsByTagName('script');
        for(var j = 0; j < scripts.length; j++){
            var src = scripts[j].getAttribute('src');
            if(src){
                static_data_list.push(src);
            }
        }
        return Promise.resolve(static_data_list);
    })
    .then(function(list){
        console.log(list);
        return Promise.all(list.map(function(file_path){
            return getStaticData(file_path, req.body.url);
        }));
    })
    .then(function(result){
        for(var i = 0; i < result.length; i++){
            // console.log(result[i].name);
            // console.log(result[i].body);
            files.push(result[i]);
        }
        files.map(function(file){
            fs.writeFile('./staticFiles/'+ file.name, file.body);
        });
        return Promise.resolve(files);
    })
    .then(function(){
        var len = files.length;
        var points = [];
        for(var i = 0; i < len; i++){
            files[i].points = checkLegacy(files[i]);
        }
    })
    .then(function(){
        results[req.sessionID].score = 100;
        results[req.sessionID].status = 'done';
    });
});

app.post('/score', function(req, res){
    if(!results[req.sessionID]) {
        res.status(400);
        res.send('あなたからのリクエストを受けていないかタイムアウトしました');
        res.end();
    } else {
        var result = results[req.sessionID];
        var interval = setInterval(function(){
            if(result.status == 'done'){
                res.status(200);
                res.send(String(result.score));
                res.end();
                clearInterval(interval);
            } else if(result.status == 'error'){
                res.status(500);
                res.send('診断中にエラーが発生しました');
                res.end();
                clearInterval(interval);
            }
        }, 1000);
        setTimeout(function(){
            clearInterval(interval);
        }, 60000);
    }
});

app.post('/detail', function(req, res){
    if(!results[req.sessionID]) {
        res.status(400);
        res.send('あなたからのリクエストを受けていないかタイムアウトしました');
        res.end();
    } else {

    }
});

app.listen(58000);
console.log('server is running at localhost:58000');

function getStaticData(file_path, page_url){
    var file = {};
    file.name = path.basename(file_path);
    var file_url = url.resolve(page_url, file_path);
    console.log(file_url);
    return request.getAsync(file_url)
    .then(function(result){
        file.body = result[1];
        return Promise.resolve(file);
    });
}
<commit_msg>return dummy point<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var request = require('request');
var fs = require('fs');
var jsdom = require("jsdom");
var Promise = require('bluebird');
var path = require('path');
var url = require('url');

Promise.promisifyAll(request);
Promise.promisifyAll(fs);
Promise.promisifyAll(jsdom);

var app = express();

var results = {};

app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    resave: false,
    saveUninitialized: true,
    secret: 'keyboard cat',
    cookie: {
        maxAge: 300000
    }
}));

app.use(function(req, res, next){
    console.log(req.session);
    console.log(req.sessionID);
    next();
});

app.use(express.static(__dirname + '/public'));
app.post('/grade', function(req, res){
    results[req.sessionID] = {stauts: 'processing'};
    res.status(200);
    res.redirect('/result');
    res.end();
    var files = [];
    request.getAsync(req.body)
    .then(function(result){
        var body = result[1];
        files.push({
            name: 'index.html',
            body: body
        });
        return jsdom.envAsync(body);
    })
    .then(function(window){
        var static_data_list = [];
        var links = window.document.getElementsByTagName('link');
        for(var i = 0; i < links.length; i++){
            var href = links[i].getAttribute('href');
            var rel = links[i].getAttribute('rel');
            if(href && rel == 'stylesheet'){
                static_data_list.push(href);
            }
        }
        var scripts = window.document.getElementsByTagName('script');
        for(var j = 0; j < scripts.length; j++){
            var src = scripts[j].getAttribute('src');
            if(src){
                static_data_list.push(src);
            }
        }
        return Promise.resolve(static_data_list);
    })
    .then(function(list){
        console.log(list);
        return Promise.all(list.map(function(file_path){
            return getStaticData(file_path, req.body.url);
        }));
    })
    .then(function(result){
        for(var i = 0; i < result.length; i++){
            // console.log(result[i].name);
            // console.log(result[i].body);
            files.push(result[i]);
        }
        files.map(function(file){
            fs.writeFile('./staticFiles/'+ file.name, file.body);
        });
        return Promise.resolve(files);
    })
    .then(function(){
        var len = files.length;
        var points = [];
        for(var i = 0; i < len; i++){
            files[i].points = checkLegacy(files[i]);
        }
        Promise.resolve();
    })
    .then(function(){
        var result = results[req.sessionID];
        result.score = 100;
        result.status = 'done';
        result.files = files;
    });
});

app.post('/score', function(req, res){
    if(!results[req.sessionID]) {
        res.status(400);
        res.send('あなたからのリクエストを受けていないかタイムアウトしました');
        res.end();
    } else {
        var result = results[req.sessionID];
        var interval = setInterval(function(){
            if(result.status == 'done'){
                res.status(200);
                res.send(String(result.score));
                res.end();
                clearInterval(interval);
            } else if(result.status == 'error'){
                res.status(500);
                res.send('診断中にエラーが発生しました');
                res.end();
                clearInterval(interval);
            }
        }, 1000);
        setTimeout(function(){
            clearInterval(interval);
        }, 60000);
    }
});

app.get('/point', function(req, res){
    if(!results[req.sessionID]) {
        res.status(400);
        res.send('あなたからのリクエストを受けていないかタイムアウトしました');
        res.end();
    } else {
        res.status(200);
        res.send(JSON.stringify(results[req.sessionID]));
        res.end();
    }
});

app.listen(58000);
console.log('server is running at localhost:58000');

function getStaticData(file_path, page_url){
    var file = {};
    file.name = path.basename(file_path);
    var file_url = url.resolve(page_url, file_path);
    console.log(file_url);
    return request.getAsync(file_url)
    .then(function(result){
        file.body = result[1];
        return Promise.resolve(file);
    });
}

function checkLegacy(file){
    var points = [];
    for(var i = 0; i < 2; i++){
        var line = Math.random() * file.body.length;
        points.push({
            line: line,
            comment: '書き方が古いです',
            type: 'old_rule'
        });
    }
    return points;
}
<|endoftext|>