<commit_before>var MjsController = function(mjs, notification, item, auth, $rootScope, $scope,
                             $state, $stateParams, $http, apiClient, langManager) {
	var self = this;
	this.notification = notification;
	this.mjs = mjs;
	this.auth = auth;
	this.item = item;
	this.selected_branch = 0;
	this.mjs_items = [];
	this.$scope = $scope;
	this.branch_edit_status = {
            1: false,
            2: false,
            3: false,
            4: false,
    };
    this.in_rename_mode = false;
	this.rmdialog_status = false;
	this.in_edit_mode = false;
    this.langManager = langManager;
	this.$rootScope = $rootScope;

	Object.defineProperty(this, 'signedin', {
		get: function() {
			return auth.is_signedin();
		}
	});

  if ($stateParams.user_id) {
    // another user's story - story.html
	self.public_url = $state.href('story',{user_id: $stateParams.user_id},
								  {absolute: true});
    $http.get(apiClient.urls.story+'/'+$stateParams.user_id)
         .then(function(res) {
           var items_ids = []
           self.user = res.data;
		   self.refresh_root_scope();
           res.data.story_items.forEach(function(i) {
             items_ids.push(i.id)
           });
           self.load(items_ids);
         });
  }
  else {
    // logged in user story - mjs.html
    if(!auth.user) {
      $rootScope.$on('loggedin', function(event, user) {
        var items_ids = [];
        self.user = user;
	    self.refresh_root_scope();
        user.story_items.forEach(function (i) {
          items_ids.push(i.id)
        })
        self.load(items_ids);
        self.public_url = $state.href('story',{user_id: user.hash},{absolute: true});
      });
    } else {
      var items_ids = mjs.get_items_ids();
      self.user = auth.user;
      self.public_url = $state.href('story',{user_id: self.user.hash},{absolute: true});
	  self.refresh_root_scope();
      if (items_ids.length > 0) {
        self.load(items_ids);
      }
    }
  };

	$rootScope.$on('item-removed', function(events, item_slug) {
		var mjs_items = [];
		for (var i in self.mjs_items) {
			if(self.mjs_items[i].Slug.En != item_slug) {
				mjs_items.push(self.mjs_items[i]);
			}
		}
		self.mjs_items = mjs_items;
	});
};

MjsController.prototype = {
	init: function() {
		var self = this;
		self.load(this.mjs.get_items_ids());
	},

	load: function(items_ids) {
		var self = this;

		this.mjs_items = [];
		this.notification.loading(true);

		this.item.get_items(items_ids).then(function (items) {
        var counters = [0,0,0,0]
        items.forEach(function (item_data) {
          var item_string = self.item.get_key(item_data);
          self.user.story_items.every(function(item) {
              if (item_string == item.id) {
                  item_data.in_branch = item.in_branch.slice();
                  return false;
              }
              return true;
          });
          item_data.in_branch.forEach(function(in_branch, i) {
            if (in_branch)
              counters[i] += 1;
          });
        });
				self.mjs_items = items;
        self.items_counters = counters;

		}).finally(function() { self.notification.loading(false); });
	},

	stopPropagation: function($event) {
		$event.stopPropagation();
	},

	rename_branch: function(branch_num, new_name) {
		this.mjs.rename_branch(branch_num, new_name);
	},

	rename_user: function(new_name) {
        var current_lang = this.langManager.lang;
		this.mjs.rename_user(new_name, current_lang);
	},

	toggle_branch_edit: function(branch_num)  {
		if (this.branch_edit_status[branch_num]) {
			this.branch_edit_status[branch_num] = false;
			this.in_edit_mode = false;
		}
		else {
			for(var branch in this.branch_edit_status) {
				if (this.branch_edit_status[branch] && branch != branch_num) {
					this.branch_edit_status[branch] = false;
					break;
				}
			}
			this.branch_edit_status[branch_num] = true;
			this.in_edit_mode = true;
		}
	},

	navigate_to_branch: function(branch_num) {
		this.selected_branch = branch_num;
	},

	toggle_branch_rmdialog: function()  {
		this.rmdialog_status = !(this.rmdialog_status);

	},
	refresh_root_scope: function() {
		var $rootScope = this.$rootScope;
			language_map = {'en': 'En', 'he': 'He'},
			lang = language_map[$rootScope.lang],
			branches = this.user.story_branches
								.filter(function(a) {return a!=''})
								.join(', ');

								debugger;
		if (lang == 'En') {
			if (this.user.name && this.user.name.en) {
				$rootScope.title = this.user.name.en + " Family Story";
				$rootScope.description = this.user.name.en + " has collected photos, stories ";
			}
			else {
				$rootScope.title = "My Family Story";
				$rootScope.description = "A collection of photos, stories ";
			}
			if (branches)
				$rootScope.description += "divided into the "+branches+" branches.";
			else
				$rootScope.description += "and more.";
		}
		else {
			if (this.user.name && this.user.name.he) {
				$rootScope.title = "סיפור המשפחה של " + this.user.name.he;
				$rootScope.description = "אסף תמונות ומאמרים אודות המשפחתה של " + this.user.name.he + ".";
			}
			else {
				$rootScope.title = "סיפור משפחתי";
				$rootScope.description = "אוסף תמונות ומאמרים אודות המשפחה.";
			}
			if (branches)
				$rootScope.description += " האוסף כולל את הענפים: "+branches;
		}
	}
};

angular.module('main').controller('MjsController', ['mjs', 'notification',
								  'item', 'auth', '$rootScope', '$scope', '$state',
                  '$stateParams', '$http', 'apiClient', 'langManager',
                  MjsController]);
<commit_msg>squashing a `debugger`<commit_after>var MjsController = function(mjs, notification, item, auth, $rootScope, $scope,
                             $state, $stateParams, $http, apiClient, langManager) {
	var self = this;
	this.notification = notification;
	this.mjs = mjs;
	this.auth = auth;
	this.item = item;
	this.selected_branch = 0;
	this.mjs_items = [];
	this.$scope = $scope;
	this.branch_edit_status = {
            1: false,
            2: false,
            3: false,
            4: false,
    };
    this.in_rename_mode = false;
	this.rmdialog_status = false;
	this.in_edit_mode = false;
    this.langManager = langManager;
	this.$rootScope = $rootScope;

	Object.defineProperty(this, 'signedin', {
		get: function() {
			return auth.is_signedin();
		}
	});

  if ($stateParams.user_id) {
    // another user's story - story.html
	self.public_url = $state.href('story',{user_id: $stateParams.user_id},
								  {absolute: true});
    $http.get(apiClient.urls.story+'/'+$stateParams.user_id)
         .then(function(res) {
           var items_ids = []
           self.user = res.data;
		   self.refresh_root_scope();
           res.data.story_items.forEach(function(i) {
             items_ids.push(i.id)
           });
           self.load(items_ids);
         });
  }
  else {
    // logged in user story - mjs.html
    if(!auth.user) {
      $rootScope.$on('loggedin', function(event, user) {
        var items_ids = [];
        self.user = user;
	    self.refresh_root_scope();
        user.story_items.forEach(function (i) {
          items_ids.push(i.id)
        })
        self.load(items_ids);
        self.public_url = $state.href('story',{user_id: user.hash},{absolute: true});
      });
    } else {
      var items_ids = mjs.get_items_ids();
      self.user = auth.user;
      self.public_url = $state.href('story',{user_id: self.user.hash},{absolute: true});
	  self.refresh_root_scope();
      if (items_ids.length > 0) {
        self.load(items_ids);
      }
    }
  };

	$rootScope.$on('item-removed', function(events, item_slug) {
		var mjs_items = [];
		for (var i in self.mjs_items) {
			if(self.mjs_items[i].Slug.En != item_slug) {
				mjs_items.push(self.mjs_items[i]);
			}
		}
		self.mjs_items = mjs_items;
	});
};

MjsController.prototype = {
	init: function() {
		var self = this;
		self.load(this.mjs.get_items_ids());
	},

	load: function(items_ids) {
		var self = this;

		this.mjs_items = [];
		this.notification.loading(true);

		this.item.get_items(items_ids).then(function (items) {
        var counters = [0,0,0,0]
        items.forEach(function (item_data) {
          var item_string = self.item.get_key(item_data);
          self.user.story_items.every(function(item) {
              if (item_string == item.id) {
                  item_data.in_branch = item.in_branch.slice();
                  return false;
              }
              return true;
          });
          item_data.in_branch.forEach(function(in_branch, i) {
            if (in_branch)
              counters[i] += 1;
          });
        });
				self.mjs_items = items;
        self.items_counters = counters;

		}).finally(function() { self.notification.loading(false); });
	},

	stopPropagation: function($event) {
		$event.stopPropagation();
	},

	rename_branch: function(branch_num, new_name) {
		this.mjs.rename_branch(branch_num, new_name);
	},

	rename_user: function(new_name) {
        var current_lang = this.langManager.lang;
		this.mjs.rename_user(new_name, current_lang);
	},

	toggle_branch_edit: function(branch_num)  {
		if (this.branch_edit_status[branch_num]) {
			this.branch_edit_status[branch_num] = false;
			this.in_edit_mode = false;
		}
		else {
			for(var branch in this.branch_edit_status) {
				if (this.branch_edit_status[branch] && branch != branch_num) {
					this.branch_edit_status[branch] = false;
					break;
				}
			}
			this.branch_edit_status[branch_num] = true;
			this.in_edit_mode = true;
		}
	},

	navigate_to_branch: function(branch_num) {
		this.selected_branch = branch_num;
	},

	toggle_branch_rmdialog: function()  {
		this.rmdialog_status = !(this.rmdialog_status);

	},
	refresh_root_scope: function() {
		var $rootScope = this.$rootScope;
			language_map = {'en': 'En', 'he': 'He'},
			lang = language_map[$rootScope.lang],
			branches = this.user.story_branches
								.filter(function(a) {return a!=''})
								.join(', ');

		if (lang == 'En') {
			if (this.user.name && this.user.name.en) {
				$rootScope.title = this.user.name.en + " Family Story";
				$rootScope.description = this.user.name.en + " has collected photos, stories ";
			}
			else {
				$rootScope.title = "My Family Story";
				$rootScope.description = "A collection of photos, stories ";
			}
			if (branches)
				$rootScope.description += "divided into the "+branches+" branches.";
			else
				$rootScope.description += "and more.";
		}
		else {
			if (this.user.name && this.user.name.he) {
				$rootScope.title = "סיפור המשפחה של " + this.user.name.he;
				$rootScope.description = "אסף תמונות ומאמרים אודות המשפחתה של " + this.user.name.he + ".";
			}
			else {
				$rootScope.title = "סיפור משפחתי";
				$rootScope.description = "אוסף תמונות ומאמרים אודות המשפחה.";
			}
			if (branches)
				$rootScope.description += " האוסף כולל את הענפים: "+branches;
		}
	}
};

angular.module('main').controller('MjsController', ['mjs', 'notification',
								  'item', 'auth', '$rootScope', '$scope', '$state',
                  '$stateParams', '$http', 'apiClient', 'langManager',
                  MjsController]);
<|endoftext|>


<commit_before>var browsers = {};
var secrets = {};
if ((function () {
    try {
        secrets = require("./secrets");
        return true;
    } catch(e) {
        if (e.code !== 'MODULE_NOT_FOUND') {
            throw e;
        }
        return false;
    }
})()) {
    browsers = require("./karma-browsers");
    Object.keys(browsers).forEach(function(key) {
        browsers[key].base = "BrowserStack";
    });
}
var webpackConfig = require("./webpack.config");

module.exports = function(config) {
    config.set({
        frameworks: ["mocha"],
        files: ["**/test/**/test_*.js"],
        exclude: ["**/node_modules/**/test/**/test_*.js"],
        preprocessors: {
            "**/test/**/test_*.js": ["webpack"]
        },
        webpack: {
            module: webpackConfig.module,
            resolve: webpackConfig.resolve,
            plugins: webpackConfig.plugins
        },
        concurrency: 2,
        browsers: Object.keys(browsers),
        browserStack: {
            username: process.env.BS_USERNAME || secrets.BS_USERNAME,
            accessKey: process.env.BS_AUTHKEY || secrets.BS_AUTHKEY,
            project: process.env.CIRCLE_PROJECT_REPONAME + "_" + process.env.CIRCLE_BRANCH || "frame_local",
            build: process.env.CIRCLE_BUILD_NUM || Date.now()
        },
        customLaunchers: browsers
    });
};
<commit_msg>Code complexity を改善しました。<commit_after>var browsers = {};
var secrets = {};
if ((function () {
    try {
        secrets = require("./secrets");
        return true;
    } catch(e) {
        if (e.code !== "MODULE_NOT_FOUND") {
            throw e;
        }
        return false;
    }
})()) {
    browsers = require("./karma-browsers");
    Object.keys(browsers).forEach(function(key) {
        browsers[key].base = "BrowserStack";
    });
}
var webpackConfig = require("./webpack.config");
var browserStackConfig = {
    username: process.env.BS_USERNAME || secrets.BS_USERNAME,
    accessKey: process.env.BS_AUTHKEY || secrets.BS_AUTHKEY,
    project: process.env.CIRCLE_PROJECT_REPONAME + "_" + process.env.CIRCLE_BRANCH || "frame_local",
    build: process.env.CIRCLE_BUILD_NUM || Date.now()
};

module.exports = function(config) {
    config.set({
        frameworks: ["mocha"],
        files: ["**/test/**/test_*.js"],
        exclude: ["**/node_modules/**/test/**/test_*.js"],
        preprocessors: {
            "**/test/**/test_*.js": ["webpack"]
        },
        webpack: {
            module: webpackConfig.module,
            resolve: webpackConfig.resolve,
            plugins: webpackConfig.plugins
        },
        concurrency: 2,
        browsers: Object.keys(browsers),
        browserStack: browserStackConfig,
        customLaunchers: browsers
    });
};
<|endoftext|>


<commit_before>function CPF_CNPJ(numdoc) {
    this.numdoc = numdoc.toString().replace(/[^0-9]/g, '');
    this.valido = false;
    this.tipo = false;
    this.formatado = false;

    if (this.numdoc.length === 11) {
        this.tipo = "CPF";
    } else if (this.numdoc.length == 14) {
        this.tipo = "CNPJ";
    } else
        return this;

    if (this.tipo == "CPF") {
        var digitos = this.numdoc.substr(0, 9);
        var novo_cpf = this.cdp(digitos, 10);
        var novo_cpf = this.cdp(novo_cpf, 11);
        this.valido = (novo_cpf == this.numdoc);

        if (this.valido) {
            this.formatado = this.numdoc.substr(0, 3) + '.' + this.numdoc.substr(3, 3) + '.' + this.numdoc.substr(6, 3) + '-' + fthis.numdoc.substr(9, 2) + '';
        }
    } else if (this.tipo == "CNPJ") {
        var digitos = this.numdoc.substr(0, 12);
        var novo_cnpj = this.cdp(digitos, 5);
        var novo_cnpj = this.cdp(novo_cnpj, 6);
        this.valido = (novo_cnpj == this.numdoc);
        if (this.valido) {
            this.formatado = this.numdoc.substr(0, 2) + '.' + this.numdoc.substr(2, 3) + '.' + this.numdoc.substr(5, 3) + '/' + this.numdoc.substr(8, 4) + '-' + this.numdoc.substr(12, 14) + '';
        }
    }
}

CPF_CNPJ.prototype.cdp = function(d, p) {
    var s = 0;
    for (var i = 0; i < d.length; i++) {
        s+=(d[i] * p);
        p--;
        if (p < 2) {
            p = 9;
        }
    }

    s = s % 11;
    s = (s < 2) ? 0 : 11 - s;
    return d + s;
};
<commit_msg>Update cpf_cnpj.js<commit_after>function CPF_CNPJ(numdoc) {
    this.numdoc = numdoc.toString().replace(/[^0-9]/g, '');
    this.valido = false;
    this.tipo = false;
    this.formatado = false;

    if (this.numdoc.length === 11) {
        this.tipo = "CPF";
    } else if (this.numdoc.length == 14) {
        this.tipo = "CNPJ";
    } else
        return this;

    this.cdp = function(d, p) {
        var s = 0;
        for (var i = 0; i < d.length; i++) {
            s+=(d[i] * p);
            p--;
            if (p < 2) {
                p = 9;
            }
        };
        s = s % 11;
        s = (s < 2) ? 0 : 11 - s;
        return d + s;
    };

    if (this.tipo == "CPF") {
        var digitos = this.numdoc.substr(0, 9);
        var novo_cpf = this.cdp(digitos, 10);
        var novo_cpf = this.cdp(novo_cpf, 11);
        this.valido = (novo_cpf == this.numdoc);

        if (this.valido) {
            this.formatado = this.numdoc.substr(0, 3) + '.' + this.numdoc.substr(3, 3) + '.' + this.numdoc.substr(6, 3) + '-' + fthis.numdoc.substr(9, 2) + '';
        }
    } else if (this.tipo == "CNPJ") {
        var digitos = this.numdoc.substr(0, 12);
        var novo_cnpj = this.cdp(digitos, 5);
        var novo_cnpj = this.cdp(novo_cnpj, 6);
        this.valido = (novo_cnpj == this.numdoc);
        if (this.valido) {
            this.formatado = this.numdoc.substr(0, 2) + '.' + this.numdoc.substr(2, 3) + '.' + this.numdoc.substr(5, 3) + '/' + this.numdoc.substr(8, 4) + '-' + this.numdoc.substr(12, 14) + '';
        }
    }
}
<|endoftext|>


<commit_before>
window.rhubarb.vb.create("Html5FileUploadViewBridge", function(parent){
    return {
        onReady: function () {
            parent.onReady.call(this);
            if (this.supportsHtml5Uploads()) {

                this.originalFileInput = this.viewNode;

                // An array of files to upload.
                this.filesToUpload = [];
                this.activeUploadIndex = -1;

                this.createUploadProgressIndicatorContainer();

                var self = this;
                this.originalFileInput.addEventListener("change", function () {
                    self.onFilesSelected(this.files);
                    self.originalFileInput.value = '';
                }, false);
            }
        },
        createUploadProgressIndicatorContainer: function () {
            this.uploadProgressIndicatorContainer = document.createElement("div");
            this.uploadProgressIndicatorContainer.className = "upload-progress-container";

            this.originalFileInput.parentNode.insertBefore(
                this.uploadProgressIndicatorContainer,
                this.originalFileInput);
        },
        updateDom: function(){
            if (this.uploading){
                var activeUpload = this.filesToUpload[this.activeUploadIndex];

                if (!this.uploadProgressIndicator){
                    this.uploadProgressIndicator = this.createUploadProgressIndicator();
                    this.uploadProgressIndicatorContainer.appendChild(this.uploadProgressIndicator);
                }

                this.updateUploadProgressIndicator(this.uploadProgressIndicator, activeUpload.progress);
                this.uploadProgressIndicator.style.display = 'block';
                this.originalFileInput.style.display = 'none';
            } else {

                if (this.uploadProgressIndicator) {
                    this.uploadProgressIndicator.style.display = 'none';
                }

                this.originalFileInput.style.display = 'block';
            }
        },
        updateUploadProgressIndicator: function (progressIndicator, progressDetails) {
            progressIndicator.needle.style.width = progressDetails.percentage + "%";
            progressIndicator.label.innerHTML = progressDetails.name;
            progressIndicator.speed.innerHTML =
                (progressDetails.speed) ?
                    this.formatSpeed(progressDetails.speed) :
                    '';
            progressIndicator.remaining.innerHTML =
                (progressDetails.remaining) ?
                    this.formatRemaining(progressDetails.remaining) + ' remaining' :
                    '';
            progressIndicator.overall.innerHTML = (this.activeUploadIndex + 1) + ' of ' + this.filesToUpload.length;
        },
        onFilesSelected: function (files) {
            for (var i = 0; i < files.length; i++) {
                this.filesToUpload.push(files[i]);
            }

            this.uploadNextFile();
        },
        onUploadComplete: function (response) {
            if (this.uploadProgressIndicator) {
                this.uploadProgressIndicator.classList.add("-is-complete");
                this.uploadProgressIndicator.cancel.style.display = "none";
                this.uploadProgressIndicator.label.innerHTML = "Upload complete";
                var self = this;
                setTimeout(function () {
                    self.uploadProgressIndicator.parentNode.removeChild(self.uploadProgressIndicator);
                    self.viewNode.style.display = "block";
                }, 1500);
            }
        },
        clearQueue: function(){
            this.activeUploadIndex = -1;
            this.filesToUpload = [];
        },
        createUploadProgressIndicator: function () {
            var self = this;
            var upiDom = document.createElement("div");
            upiDom.className = "upload-progress";

            var upiGauge = document.createElement("div");
            upiGauge.className = "_gauge";

            var upiNeedle = document.createElement("div");
            upiNeedle.className = "_needle";

            var upiDetails = document.createElement('div');
            var upiLabel = document.createElement("span");
            var upiSpeed = document.createElement("span");
            var upiOverall = document.createElement("span");
            var upiRemaining = document.createElement("span");

            var cancel = document.createElement("a");
            cancel.className = "c-button c-button--neg c-button--small cancel";
            cancel.innerHTML = "Cancel Upload";
            cancel.onclick = function () {
                var confirmAbort = confirm("Are you sure you want to cancel the upload?");
                if (confirmAbort) {
                    self.uploading = false;
                    self.request.abort();
                    self.clearQueue();
                    self.updateDom();

                    self.raiseClientEvent("UploadCancelled")
                }
            };

            upiGauge.appendChild(upiNeedle);

            if (this.model.indicators.currentFileName) {
                upiDetails.appendChild(upiLabel);
            }

            if (this.model.indicators.uploadSpeed) {
                upiDetails.appendChild(upiSpeed);
            }
            if (this.model.indicators.timeRemaining) {
                upiDetails.appendChild(upiRemaining);
            }

            if (this.model.indicators.overallProgress && this.model.allowMultipleUploads) {
                upiDetails.appendChild(upiOverall);
            }

            upiDom.appendChild(upiGauge);
            upiDom.appendChild(upiDetails);
            upiDom.appendChild(cancel);

            // Put the sub elements on the parent as direct children for faster access later.
            upiDom.needle = upiNeedle;
            upiDom.details = upiDetails;
            upiDom.speed = upiSpeed;
            upiDom.overall = upiOverall;
            upiDom.label = upiLabel;
            upiDom.remaining = upiRemaining;
            upiDom.cancel = cancel;
            return upiDom;
        },
        supportsHtml5Uploads: function () {
            var xhr = new XMLHttpRequest();

            return !(!xhr.upload || !window.File || !window.FileList || !window.FileReader);
        },
        uploadNextFile: function() {
            this.uploading = false;

            this.activeUploadIndex++;

            if (this.activeUploadIndex >= this.filesToUpload.length){
                this.clearQueue();
            } else {
                this.uploadFile(this.filesToUpload[this.activeUploadIndex]);
            }

            this.updateDom();
        },
        calculateSpeed: function(previousBytesUploaded, previousTime, currentBytesUploaded) {
            var currentTime = Date.now();

            if ((currentTime - previousTime) > 333) {
                var recentBytes = currentBytesUploaded - previousBytesUploaded;
                var seconds = currentTime - previousTime;

                var speed = recentBytes / (seconds);

                return speed * 1000;
            }

            return false;
        },
        formatRemaining: function(seconds){
            var levels = [
                [Math.floor(seconds / 31536000), 'years'],
                [Math.floor((seconds % 31536000) / 86400), 'days'],
                [Math.floor(((seconds % 31536000) % 86400) / 3600), 'hours'],
                [Math.floor((((seconds % 31536000) % 86400) % 3600) / 60), 'minutes'],
                [(((seconds % 31536000) % 86400) % 3600) % 60, 'seconds'],
            ];
            var returntext = '';

            for (var i = 0, max = levels.length; i < max; i++) {
                if ( levels[i][0] === 0 ) {
                    continue;
                }
                returntext += ' ' + levels[i][0] + ' ' + (levels[i][0] === 1 ? levels[i][1].substr(0, levels[i][1].length-1): levels[i][1]);
            };
            return returntext.trim();
        },
        formatSpeed: function(speed){
            if (!speed){
                return false;
            }

            // Ensures the upload speed is displayed as a number between 1 and 1000 with correct units
            var units = 0;
            while (speed > 1000) {
                speed /= 1000;
                units++;
            }

            var displayUnits;

            switch (units) {
                case 0:
                    displayUnits = "b/s";
                    speed = parseInt(speed);
                    break;
                case 1:
                    displayUnits = "Kb/s";
                    speed = parseInt(speed);
                    break;
                case 2:
                    displayUnits = "Mb/s";
                    speed = parseFloat(speed).toPrecision(3);
                    break;
                case 3:
                    displayUnits = "Gb/s";
                    speed = parseFloat(speed).toPrecision(3);
                    break;
            }

            return speed + displayUnits;
        },
        calculateSecondsRemaining: function(speed, bytesToGo) {
            if (!speed){
                return false;
            }

            return Math.round(bytesToGo / speed);
        },
        uploadFile: function (file) {
            // Initialisation of variables for upload speed calculation:
            var displaySpeed = false;
            var totalUploaded = 0;
            var previousTime = Date.now();
            var lastSpeed = false;

            this.uploading = true;

            // Put a progress structure onto the file upload itself.
            file.progress = {
                "name": file.name,
                "position": 0,
                "length": file.length,
                "percentage": 0,
                "speed": false,
                "remaining": false
            };

            this.raiseClientEvent("UploadStarted", file);

            this.request = this.sendFileAsServerEvent(
                "fileUploaded",
                file,
                function (e) {
                    var speed = this.calculateSpeed(totalUploaded, previousTime, e.loaded);

                    if (speed){
                        // Updates for the next cycle
                        previousTime = Date.now();
                        totalUploaded = e.loaded;
                        lastSpeed = speed;
                    } else {
                        speed = lastSpeed;
                    }

                    // Update progress structure on the file upload itself.
                    file.progress = {
                        "name": file.name,
                        "position": e.loaded,
                        "length": e.total,
                        "percentage": parseInt(( e.loaded / e.total ) * 100),
                        "speed": speed,
                        "remaining": this.calculateSecondsRemaining(speed, e.total - e.loaded)
                    };

                    this.raiseClientEvent("ProgressReported", file, file.progress);

                    this.updateDom();
                }.bind(this),
                // On complete
                function (response) {
                    if (file) {
                        this.raiseClientEvent("UploadCompleted", file);
                        this.onUploadComplete(file, response);
                    }

                    this.uploadNextFile();
                    this.raiseClientEvent("UploadComplete", file, response);
                }.bind(this),
                // On failure
                function (response) {

                    this.uploadNextFile();
                    this.raiseClientEvent("UploadFailed", file, response);
                }.bind(this)
            );

            return this.request;
        }
    };
}, window.rhubarb.viewBridgeClasses.SimpleFileUploadViewBridge);

//bridge.prototype = new window.rhubarb.viewBridgeClasses.SimpleFileUploadViewBridge();
<commit_msg>Better classes for morse compat<commit_after>
window.rhubarb.vb.create("Html5FileUploadViewBridge", function(parent){
    return {
        onReady: function () {
            parent.onReady.call(this);
            if (this.supportsHtml5Uploads()) {

                this.originalFileInput = this.viewNode;

                // An array of files to upload.
                this.filesToUpload = [];
                this.activeUploadIndex = -1;

                this.createUploadProgressIndicatorContainer();

                var self = this;
                this.originalFileInput.addEventListener("change", function () {
                    self.onFilesSelected(this.files);
                    self.originalFileInput.value = '';
                }, false);
            }
        },
        createUploadProgressIndicatorContainer: function () {
            this.uploadProgressIndicatorContainer = document.createElement("div");
            this.uploadProgressIndicatorContainer.className = "c-file-upload-container";

            this.originalFileInput.parentNode.insertBefore(
                this.uploadProgressIndicatorContainer,
                this.originalFileInput);
        },
        updateDom: function(){
            if (this.uploading){
                var activeUpload = this.filesToUpload[this.activeUploadIndex];

                if (!this.uploadProgressIndicator){
                    this.uploadProgressIndicator = this.createUploadProgressIndicator();
                    this.uploadProgressIndicatorContainer.appendChild(this.uploadProgressIndicator);
                }

                this.updateUploadProgressIndicator(this.uploadProgressIndicator, activeUpload.progress);
                this.uploadProgressIndicator.style.display = 'block';
                this.originalFileInput.style.display = 'none';
            } else {

                if (this.uploadProgressIndicator) {
                    this.uploadProgressIndicator.style.display = 'none';
                }

                this.originalFileInput.style.display = 'block';
            }
        },
        updateUploadProgressIndicator: function (progressIndicator, progressDetails) {
            progressIndicator.needle.style.width = progressDetails.percentage + "%";
            progressIndicator.label.innerHTML = progressDetails.name;
            progressIndicator.speed.innerHTML =
                (progressDetails.speed) ?
                    this.formatSpeed(progressDetails.speed) :
                    '';
            progressIndicator.remaining.innerHTML =
                (progressDetails.remaining) ?
                    this.formatRemaining(progressDetails.remaining) + ' remaining' :
                    '';
            progressIndicator.overall.innerHTML = (this.activeUploadIndex + 1) + ' of ' + this.filesToUpload.length;
        },
        onFilesSelected: function (files) {
            for (var i = 0; i < files.length; i++) {
                this.filesToUpload.push(files[i]);
            }

            this.uploadNextFile();
        },
        onUploadComplete: function (response) {
            if (this.uploadProgressIndicator) {
                this.uploadProgressIndicator.classList.add("-is-complete");
                this.uploadProgressIndicator.cancel.style.display = "none";
                this.uploadProgressIndicator.label.innerHTML = "Upload complete";
                var self = this;
                setTimeout(function () {
                    self.uploadProgressIndicator.parentNode.removeChild(self.uploadProgressIndicator);
                    self.viewNode.style.display = "block";
                }, 1500);
            }
        },
        clearQueue: function(){
            this.activeUploadIndex = -1;
            this.filesToUpload = [];
        },
        createUploadProgressIndicator: function () {
            var self = this;
            var upiDom = document.createElement("div");
            upiDom.className = "c-file-upload upload-progress";

            var upiGauge = document.createElement("div");
            upiGauge.className = "c-file-upload__progress _gauge";

            var upiNeedle = document.createElement("div");
            upiNeedle.className = "c-file-upload__progress-bar _needle";

            var upiLabel = document.createElement("span");
            upiLabel.className = "c-file-upload__label";

            var upiSpeed = document.createElement("span");
            upiSpeed.className = "c-file-upload__speed";

            var upiOverall = document.createElement("span");
            upiOverall.className = "c-file-upload__overall";

            var upiRemaining = document.createElement("span");
            upiRemaining.className = "c-file-upload__remaining";

            var cancel = document.createElement("button");
            cancel.className = "c-file-upload__button";
            cancel.innerHTML = "Cancel Upload";
            cancel.onclick = function () {
                var confirmAbort = confirm("Are you sure you want to cancel the upload?");
                if (confirmAbort) {
                    self.uploading = false;
                    self.request.abort();
                    self.clearQueue();
                    self.updateDom();

                    self.raiseClientEvent("UploadCancelled")
                }
            };

            if (this.model.indicators.currentFileName) {
                upiDom.appendChild(upiLabel);
            }

            if (this.model.indicators.uploadSpeed) {
                upiDom.appendChild(upiSpeed);
            }

            upiGauge.appendChild(upiNeedle);

            upiDom.appendChild(upiGauge);

            if (this.model.indicators.timeRemaining) {
                upiDom.appendChild(upiRemaining);
            }

            if (this.model.indicators.overallProgress && this.model.allowMultipleUploads) {
                upiDom.appendChild(upiOverall);
            }

            upiDom.appendChild(cancel);

            // Put the sub elements on the parent as direct children for faster access later.
            upiDom.needle = upiNeedle;
            upiDom.speed = upiSpeed;
            upiDom.overall = upiOverall;
            upiDom.label = upiLabel;
            upiDom.remaining = upiRemaining;
            upiDom.cancel = cancel;
            return upiDom;
        },
        supportsHtml5Uploads: function () {
            var xhr = new XMLHttpRequest();

            return !(!xhr.upload || !window.File || !window.FileList || !window.FileReader);
        },
        uploadNextFile: function() {
            this.uploading = false;

            this.activeUploadIndex++;

            if (this.activeUploadIndex >= this.filesToUpload.length){
                this.clearQueue();
            } else {
                this.uploadFile(this.filesToUpload[this.activeUploadIndex]);
            }

            this.updateDom();
        },
        calculateSpeed: function(previousBytesUploaded, previousTime, currentBytesUploaded) {
            var currentTime = Date.now();

            if ((currentTime - previousTime) > 333) {
                var recentBytes = currentBytesUploaded - previousBytesUploaded;
                var seconds = currentTime - previousTime;

                var speed = recentBytes / (seconds);

                return speed * 1000;
            }

            return false;
        },
        formatRemaining: function(seconds){
            var levels = [
                [Math.floor(seconds / 31536000), 'years'],
                [Math.floor((seconds % 31536000) / 86400), 'days'],
                [Math.floor(((seconds % 31536000) % 86400) / 3600), 'hours'],
                [Math.floor((((seconds % 31536000) % 86400) % 3600) / 60), 'minutes'],
                [(((seconds % 31536000) % 86400) % 3600) % 60, 'seconds'],
            ];
            var returntext = '';

            for (var i = 0, max = levels.length; i < max; i++) {
                if ( levels[i][0] === 0 ) {
                    continue;
                }
                returntext += ' ' + levels[i][0] + ' ' + (levels[i][0] === 1 ? levels[i][1].substr(0, levels[i][1].length-1): levels[i][1]);
            };
            return returntext.trim();
        },
        formatSpeed: function(speed){
            if (!speed){
                return false;
            }

            // Ensures the upload speed is displayed as a number between 1 and 1000 with correct units
            var units = 0;
            while (speed > 1000) {
                speed /= 1000;
                units++;
            }

            var displayUnits;

            switch (units) {
                case 0:
                    displayUnits = "b/s";
                    speed = parseInt(speed);
                    break;
                case 1:
                    displayUnits = "Kb/s";
                    speed = parseInt(speed);
                    break;
                case 2:
                    displayUnits = "Mb/s";
                    speed = parseFloat(speed).toPrecision(3);
                    break;
                case 3:
                    displayUnits = "Gb/s";
                    speed = parseFloat(speed).toPrecision(3);
                    break;
            }

            return speed + displayUnits;
        },
        calculateSecondsRemaining: function(speed, bytesToGo) {
            if (!speed){
                return false;
            }

            return Math.round(bytesToGo / speed);
        },
        uploadFile: function (file) {
            // Initialisation of variables for upload speed calculation:
            var displaySpeed = false;
            var totalUploaded = 0;
            var previousTime = Date.now();
            var lastSpeed = false;

            this.uploading = true;

            // Put a progress structure onto the file upload itself.
            file.progress = {
                "name": file.name,
                "position": 0,
                "length": file.length,
                "percentage": 0,
                "speed": false,
                "remaining": false
            };

            this.raiseClientEvent("UploadStarted", file);

            this.request = this.sendFileAsServerEvent(
                "fileUploaded",
                file,
                function (e) {
                    var speed = this.calculateSpeed(totalUploaded, previousTime, e.loaded);

                    if (speed){
                        // Updates for the next cycle
                        previousTime = Date.now();
                        totalUploaded = e.loaded;
                        lastSpeed = speed;
                    } else {
                        speed = lastSpeed;
                    }

                    // Update progress structure on the file upload itself.
                    file.progress = {
                        "name": file.name,
                        "position": e.loaded,
                        "length": e.total,
                        "percentage": parseInt(( e.loaded / e.total ) * 100),
                        "speed": speed,
                        "remaining": this.calculateSecondsRemaining(speed, e.total - e.loaded)
                    };

                    this.raiseClientEvent("ProgressReported", file, file.progress);

                    this.updateDom();
                }.bind(this),
                // On complete
                function (response) {
                    if (file) {
                        this.raiseClientEvent("UploadCompleted", file);
                        this.onUploadComplete(file, response);
                    }

                    this.uploadNextFile();
                    this.raiseClientEvent("UploadComplete", file, response);
                }.bind(this),
                // On failure
                function (response) {

                    this.uploadNextFile();
                    this.raiseClientEvent("UploadFailed", file, response);
                }.bind(this)
            );

            return this.request;
        }
    };
}, window.rhubarb.viewBridgeClasses.SimpleFileUploadViewBridge);

//bridge.prototype = new window.rhubarb.viewBridgeClasses.SimpleFileUploadViewBridge();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

import Link from 'react/components/UserDropdown/components/Link';

const SmallLink = styled(Link).attrs({
  f: 2,
  fontWeight: 'normal',
})`
`;

export default class SecondaryLinks extends Component {
  static propTypes = {
    isPremium: PropTypes.bool.isRequired,
  }

  signOut = () => {
    window.localStorage.clear();
    window.location.href = '/me/sign_out';
  }

  render() {
    const { isPremium } = this.props;

    return (

        <SmallLink href="/settings">
          Settings
        </SmallLink>

        <SmallLink href="/tools">
          More tools
        </SmallLink>

        <SmallLink href="/faqs">
          Help / FAQs
        </SmallLink>

        <SmallLink href="/tools/send-invitation">
          Send an invite
        </SmallLink>

        <SmallLink href="/about">
          About
        </SmallLink>

        {!isPremium &&
          <SmallLink color="state.premium" href="/pricing">
            Premium features
          </SmallLink>
        }

        <SmallLink onClick={this.signOut}>
          Log Out
        </SmallLink>

    );
  }
}
<commit_msg>Change help link to help.are.na<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

import Link from 'react/components/UserDropdown/components/Link';

const SmallLink = styled(Link).attrs({
  f: 2,
  fontWeight: 'normal',
})`
`;

export default class SecondaryLinks extends Component {
  static propTypes = {
    isPremium: PropTypes.bool.isRequired,
  }

  signOut = () => {
    window.localStorage.clear();
    window.location.href = '/me/sign_out';
  }

  render() {
    const { isPremium } = this.props;

    return (

        <SmallLink href="/settings">
          Settings
        </SmallLink>

        <SmallLink href="/tools">
          More tools
        </SmallLink>

        <SmallLink href="http://help.are.na">
          Help / FAQs
        </SmallLink>

        <SmallLink href="/tools/send-invitation">
          Send an invite
        </SmallLink>

        <SmallLink href="/about">
          About
        </SmallLink>

        {!isPremium &&
          <SmallLink color="state.premium" href="/pricing">
            Premium features
          </SmallLink>
        }

        <SmallLink onClick={this.signOut}>
          Log Out
        </SmallLink>

    );
  }
}
<|endoftext|>


<commit_before>/*
===============================================================================================

		Unify Project

		Homepage: unify-project.org
		License: MIT + Apache (V2)
		Copyright: 2009-2010 Deutsche Telekom AG, Germany, http://telekom.com

===============================================================================================
*/
/**
 * This class adds a lot of functionality to work together with business
 * objects which extend {@link unify.business.RemoteData}. It comes
 * with intelligent managment of the content and tries to reduce the
 * data loaded from remote to a minimum. It integrates activity indicators
 * to give the user feedback about server communication.
 */
core.Class("unify.view.RemoteView",
{
	include : [unify.view.ServiceView],

	/*
	----------------------------------------------------------------------------
		 CONSTRUCTOR
	----------------------------------------------------------------------------
	*/

	construct : function() {
		unify.view.ServiceView.call(this);

		// Connect business object
		this._getBusinessObject().addListener("completed", this.__onBusinessObjectCompleted, this);
		this.__activityIndicator = unify.ui.manager.ActivityIndicatorManager.getInstance();
	},

	/*
	----------------------------------------------------------------------------
		 MEMBERS
	----------------------------------------------------------------------------
	*/

	members :
	{
		/** {String} Version of cache which was used to render current view */
		__appliedVersion : undefined,

		/** {String} Used internally to store the rendered variant. Needs to be undefined for views without parameters */
		__appliedVariant : undefined,

		/** {Integer} ID of request. Used to identify requests in completed events */
		__requestId : null,

		/** {Object} Activity Indicator. Used to signal running requests*/
		__activityIndicator: null,

		/*
		---------------------------------------------------------------------------
			PUBLIC API
		---------------------------------------------------------------------------
		*/

		/**
		 * Reloads the data of the view
		 */
		refresh : function()
		{
			if (this.__requestId != null) {
				return;
				//this.__activityIndicator.hide(this.getHash());
			}
			this.__requestId = this._getBusinessObject().get(this._getServiceName(), this._getServiceParams());
			if (this.__requestId !== false && this.__activityIndicator) {
				this.__activityIndicator.show(this.getHash());
			}
			return this.__requestId;
		},

		/*
		---------------------------------------------------------------------------
			INTERNALS
		---------------------------------------------------------------------------
		*/

		/**
		 * sets a different activity indicator.
		 *
		 * @param indicator {unify.ui.core.Widget} Activity indicator
		 */
		_setActivityIndicator: function(indicator){
			this.__activityIndicator=indicator;
		},

		/**
		 * get the activity indicator used by this view
		 */
		getActivityIndicator: function(){
			return this.__activityIndicator;
		},

		/**
		 * Whether the view has all required parameters to send a request to
		 * the server.
		 *
		 * @return {Boolean} Whether the view has all required request data
		 */
		_hasServiceRequestParams : function() {
			return true;
		},

		/**
		 * Applies updates to the view
		 *
		 * Should be called whenever the view is active and the result of
		 * {@link #_getRenderVariant} changes or at the moment a view gets
		 * active. Changes should not be applied during the view being
		 * invisible.
		 *
		 * This method automatically checks the version of the
		 * cache which was used for a previous rendering to automatically
		 * handle refreshes.
		 */
		_checkStatus : function()
		{
			if (!this._hasServiceRequestParams()) {
				return;
			}

			var business = this._getBusinessObject();
			var service = this._getServiceName();
			var params = this._getServiceParams();
			var renderVariant = this._getRenderVariant();
			if (renderVariant !== this.__appliedVariant)
			{
				// this.debug("New render variant: " + renderVariant);

				this.__appliedVariant = renderVariant;

				var cachedEntry = business.getCachedEntry(service, params);
				if (cachedEntry == null || !business.isCacheValid(service, params))
				{
					delete this.__appliedVersion;
					this._wrappedRenderData(null);
					this.refresh();
				}
				else
				{
					delete this.__requestId;
					var hash = this.getHash();
					if(this.__activityIndicator.isShown(hash)){
						this.__activityIndicator.hide(hash);
					}
					this.__appliedVersion = cachedEntry.created;
					this._wrappedRenderData(cachedEntry.data);
				}
			}
			else
			{
				// this.debug("Same variant...");

				if (business.isCacheValid(service, params))
				{
					// this.debug("Cache is valid!")

					var cachedEntry = business.getCachedEntry(service, params);
					if (cachedEntry.created > this.__appliedVersion)
					{
						// this.debug("Cache is newer than rendered view => render with new cached data...");
						// this.debug("Rendered=" + this.__appliedVersion + " vs. Cache=" + cachedEntry.id);
						this.__appliedVersion = cachedEntry.created;
						this._wrappedRenderData(cachedEntry.data);
					}
				}
				else
				{
					// this.debug("No valid cache available. Was cleared?");
					this.refresh();
				}
			}
		},

		/**
		 * Event listener for "completed" event of business object.
		 *
		 * @param e {unify.business.CompletedEvent} Event object
		 */
		__onBusinessObjectCompleted : function(e)
		{
			if (e.getId() !== this.__requestId) {
				return;
			}

			delete this.__requestId;
			if(this.__activityIndicator){
				this.__activityIndicator.hide(this.getHash());
			}

			if (e.isErrornous()) {
				this._errorHandler("communication", e.getRequest());
			} else if (e.isMalformed()) {
				this._errorHandler("data",e.getData());
			} else if (e.isModified()) {

				var business = this._getBusinessObject();
				var service = this._getServiceName();
				var params = this._getServiceParams();
				var cachedEntry=business.getCachedEntry(service, params);
				if(cachedEntry){
					this.__appliedVersion = cachedEntry.created;
				}
				this._wrappedRenderData(e.getData());
			} else if (jasy.Env.getValue("debug")) {
				this.debug("Data was not modified!");
			}
		}
	}/*,

	/*
	----------------------------------------------------------------------------
		 DESTRUCTOR
	----------------------------------------------------------------------------
	* /

	destruct : function()
	{
		var business = this._getBusinessObject();
		if (business) {
			business.removeListener("completed", this.__onBusinessObjectCompleted, this);
		}
	} */
});
<commit_msg>added missing null check for the _activityIndicator<commit_after>/*
===============================================================================================

		Unify Project

		Homepage: unify-project.org
		License: MIT + Apache (V2)
		Copyright: 2009-2010 Deutsche Telekom AG, Germany, http://telekom.com

===============================================================================================
*/
/**
 * This class adds a lot of functionality to work together with business
 * objects which extend {@link unify.business.RemoteData}. It comes
 * with intelligent managment of the content and tries to reduce the
 * data loaded from remote to a minimum. It integrates activity indicators
 * to give the user feedback about server communication.
 */
core.Class("unify.view.RemoteView",
{
	include : [unify.view.ServiceView],

	/*
	----------------------------------------------------------------------------
		 CONSTRUCTOR
	----------------------------------------------------------------------------
	*/

	construct : function() {
		unify.view.ServiceView.call(this);

		// Connect business object
		this._getBusinessObject().addListener("completed", this.__onBusinessObjectCompleted, this);
		this.__activityIndicator = unify.ui.manager.ActivityIndicatorManager.getInstance();
	},

	/*
	----------------------------------------------------------------------------
		 MEMBERS
	----------------------------------------------------------------------------
	*/

	members :
	{
		/** {String} Version of cache which was used to render current view */
		__appliedVersion : undefined,

		/** {String} Used internally to store the rendered variant. Needs to be undefined for views without parameters */
		__appliedVariant : undefined,

		/** {Integer} ID of request. Used to identify requests in completed events */
		__requestId : null,

		/** {Object} Activity Indicator. Used to signal running requests*/
		__activityIndicator: null,

		/*
		---------------------------------------------------------------------------
			PUBLIC API
		---------------------------------------------------------------------------
		*/

		/**
		 * Reloads the data of the view
		 */
		refresh : function()
		{
			if (this.__requestId != null) {
				return;
				//this.__activityIndicator.hide(this.getHash());
			}
			this.__requestId = this._getBusinessObject().get(this._getServiceName(), this._getServiceParams());
			if (this.__requestId !== false && this.__activityIndicator) {
				this.__activityIndicator.show(this.getHash());
			}
			return this.__requestId;
		},

		/*
		---------------------------------------------------------------------------
			INTERNALS
		---------------------------------------------------------------------------
		*/

		/**
		 * sets a different activity indicator.
		 *
		 * @param indicator {unify.ui.core.Widget} Activity indicator
		 */
		_setActivityIndicator: function(indicator){
			this.__activityIndicator=indicator;
		},

		/**
		 * get the activity indicator used by this view
		 */
		getActivityIndicator: function(){
			return this.__activityIndicator;
		},

		/**
		 * Whether the view has all required parameters to send a request to
		 * the server.
		 *
		 * @return {Boolean} Whether the view has all required request data
		 */
		_hasServiceRequestParams : function() {
			return true;
		},

		/**
		 * Applies updates to the view
		 *
		 * Should be called whenever the view is active and the result of
		 * {@link #_getRenderVariant} changes or at the moment a view gets
		 * active. Changes should not be applied during the view being
		 * invisible.
		 *
		 * This method automatically checks the version of the
		 * cache which was used for a previous rendering to automatically
		 * handle refreshes.
		 */
		_checkStatus : function()
		{
			if (!this._hasServiceRequestParams()) {
				return;
			}

			var business = this._getBusinessObject();
			var service = this._getServiceName();
			var params = this._getServiceParams();
			var renderVariant = this._getRenderVariant();
			if (renderVariant !== this.__appliedVariant)
			{
				// this.debug("New render variant: " + renderVariant);

				this.__appliedVariant = renderVariant;

				var cachedEntry = business.getCachedEntry(service, params);
				if (cachedEntry == null || !business.isCacheValid(service, params))
				{
					delete this.__appliedVersion;
					this._wrappedRenderData(null);
					this.refresh();
				}
				else
				{
					delete this.__requestId;
					var hash = this.getHash();
					if(this.__activityIndicator && this.__activityIndicator.isShown(hash)){
						this.__activityIndicator.hide(hash);
					}
					this.__appliedVersion = cachedEntry.created;
					this._wrappedRenderData(cachedEntry.data);
				}
			}
			else
			{
				// this.debug("Same variant...");

				if (business.isCacheValid(service, params))
				{
					// this.debug("Cache is valid!")

					var cachedEntry = business.getCachedEntry(service, params);
					if (cachedEntry.created > this.__appliedVersion)
					{
						// this.debug("Cache is newer than rendered view => render with new cached data...");
						// this.debug("Rendered=" + this.__appliedVersion + " vs. Cache=" + cachedEntry.id);
						this.__appliedVersion = cachedEntry.created;
						this._wrappedRenderData(cachedEntry.data);
					}
				}
				else
				{
					// this.debug("No valid cache available. Was cleared?");
					this.refresh();
				}
			}
		},

		/**
		 * Event listener for "completed" event of business object.
		 *
		 * @param e {unify.business.CompletedEvent} Event object
		 */
		__onBusinessObjectCompleted : function(e)
		{
			if (e.getId() !== this.__requestId) {
				return;
			}

			delete this.__requestId;
			if(this.__activityIndicator){
				this.__activityIndicator.hide(this.getHash());
			}

			if (e.isErrornous()) {
				this._errorHandler("communication", e.getRequest());
			} else if (e.isMalformed()) {
				this._errorHandler("data",e.getData());
			} else if (e.isModified()) {

				var business = this._getBusinessObject();
				var service = this._getServiceName();
				var params = this._getServiceParams();
				var cachedEntry=business.getCachedEntry(service, params);
				if(cachedEntry){
					this.__appliedVersion = cachedEntry.created;
				}
				this._wrappedRenderData(e.getData());
			} else if (jasy.Env.getValue("debug")) {
				this.debug("Data was not modified!");
			}
		}
	}/*,

	/*
	----------------------------------------------------------------------------
		 DESTRUCTOR
	----------------------------------------------------------------------------
	* /

	destruct : function()
	{
		var business = this._getBusinessObject();
		if (business) {
			business.removeListener("completed", this.__onBusinessObjectCompleted, this);
		}
	} */
});
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const AWS = require('aws-sdk');
const rek = new AWS.Rekognition();

class ImageAnalysis {

  getImageLabels(s3Config) {
    const params = {
      Image: {
        S3Object: {
          Bucket: s3Config.bucket,
          Name: s3Config.image
        }
      },
      MaxLabels: 20,
      MinConfidence: 60
    };
    return new Promise((resolve, reject) => {
      rek.detectLabels(params, (err, data) => {
        if (err) {
          console.log(err, err.stack);
          return reject(new Error(err));
        }
        console.log('Analysis labels:', data.Labels);
        return resolve(data.Labels);
      });
    });
  }

  // Check to see if "Cat" is included in the labels
  findCat(labels) {
    return _.find(labels, ['Name', 'Cat']);
  }

  isCatImage(s3Config) {
    return this.getImageLabels(s3Config)
    .then((labels) => {
      return !!this.findCat(labels);
    });
  }
}

module.exports = ImageAnalysis;
<commit_msg>Lower confidence and allow more labels<commit_after>'use strict';

const _ = require('lodash');
const AWS = require('aws-sdk');
const rek = new AWS.Rekognition();

class ImageAnalysis {

  getImageLabels(s3Config) {
    const params = {
      Image: {
        S3Object: {
          Bucket: s3Config.bucket,
          Name: s3Config.image
        }
      },
      MaxLabels: 40,
      MinConfidence: 50
    };
    return new Promise((resolve, reject) => {
      rek.detectLabels(params, (err, data) => {
        if (err) {
          console.log(err, err.stack);
          return reject(new Error(err));
        }
        console.log('Analysis labels:', data.Labels);
        return resolve(data.Labels);
      });
    });
  }

  // Check to see if "Cat" is included in the labels
  findCat(labels) {
    return _.find(labels, ['Name', 'Cat']);
  }

  isCatImage(s3Config) {
    return this.getImageLabels(s3Config)
    .then((labels) => {
      return !!this.findCat(labels);
    });
  }
}

module.exports = ImageAnalysis;
<|endoftext|>


<commit_before>var maxmind    = require('maxmind')        // runk/node-maxmind
  , loader     = require('maxmind-loader') // angleman/maxmind-loader
  , geos       = require('geos-major')     // angleman/geos-major
  , cron       = require('cron')           // ncb000gt/node-cron
  , time       = require('time')           // TooTallNate/node-time
;

var maxmind_initialized = false;

var maxminded = function() {

	this.options = {};

	this.load_begin = function(start_callback, start_options) {
		start_options = start_options || this.options;

		function load_done(err, datapath){
			if (err) {
				this.handle_error(err);
			} else {
				maxmind.init(datapath, start_options);
				maxmind_initialized = true;
				if (start_callback) {
					start_callback(datapath);
				}
			};
		}

		loader(this.options, load_done);
	};

	this.handle_error = function (err){
		console.log(err);
		if (this.retry) {
			// todo: reschedule job
		}
	};

	this.init = function(options) {
		options          = options          || {};

		if (typeof options == 'string') {
			options      = { initLoad: options };
		};

		options.dest     = options.dest || '/tmp/';

		if (options.initLoad) {
			maxmind.init(options.initLoad, options);
			maxmind_initialized = true;
		};

		options.cronTime   = options.cronTime || '00 30 03 * * 3';

		this.options       = options;
		options.onTick     = this.load_begin;
		options.onComplete = this.load_done;
		this.job           = new cron.CronJob(options);
		this.job.start();

		if (options.start) {
			this.load_begin(options.start);
		}
	};

	// maxmind wrapper
	this.getLocation = function (ip, headers) {
		var result;
		if (maxmind_initialized) {
			result = maxmind.getLocation(ip);
		}
		if (!result && headers) {
			result = geos.country(headers['cf-ipcountry']);
		}
		return result;
	};

	// maxmind pass-thru
	this.getCountry = function (options) {
		return maxmind.getCountry(options);
	};

	this.getOrganization = function (options) {
		return maxmind.getOrganization(options);
	};
}

var minded = new maxminded;

module.exports = minded;<commit_msg>unable to find database fix<commit_after>var maxmind        = require('maxmind')        // runk/node-maxmind
  , maxmind_loader = require('maxmind-loader') // angleman/maxmind-loader
  , geos           = require('geos-major')     // angleman/geos-major
  , cron           = require('cron')           // ncb000gt/node-cron
  , time           = require('time')           // TooTallNate/node-time
;

var maxmind_initialized = false;

var maxminded = function() {

	this.options = {};

	this.load_begin = function(start_callback, start_options) {
		start_options = start_options || this.options;

		function load_done(err, datapath){
			if (err) {
				this.handle_error(err);
			} else {
				maxmind.init(datapath, start_options);
				maxmind_initialized = true;
				if (start_callback) {
					start_callback(datapath);
				}
			};
		}

		maxmind_loader(start_options, load_done);
	};

	this.handle_error = function (err){
		console.log(err);
//		if (this.retry) {
			// todo: reschedule job
//		}
	};

	this.init = function(options) {
		options          = options          || {};

		if (typeof options == 'string') {
			options      = { initLoad: options };
		};

		options.dest     = options.dest || '/tmp/';

		if (options.initLoad) {
			maxmind.init(options.initLoad, options);
			maxmind_initialized = true;
		};

		options.cronTime   = options.cronTime || '00 30 03 * * 3';

		this.options       = options;
		options.onTick     = this.load_begin;
		options.onComplete = this.load_done;
		this.job           = new cron.CronJob(options);
		this.job.start();

		if (options.start) {
			this.load_begin(options.start, options);
		}
	};

	// maxmind wrapper
	this.getLocation = function (ip, headers) {
		var result;
		if (maxmind_initialized) {
			result = maxmind.getLocation(ip);
		}
		if (!result && headers) {
			result = geos.country(headers['cf-ipcountry']);
		}
		return result;
	};

	// maxmind pass-thru
	this.getCountry = function (options) {
		return maxmind.getCountry(options);
	};

	this.getOrganization = function (options) {
		return maxmind.getOrganization(options);
	};
}

var minded = new maxminded;

module.exports = minded;<|endoftext|>


<commit_before>import Widget from "./base_widget.js";

frappe.provide("frappe.utils");

export default class QuickListWidget extends Widget {
	constructor(opts) {
		opts.shadow = true;
		super(opts);
	}

	get_config() {
		return {
			document_type: this.document_type,
			label: this.label,
			quick_list_filter: this.quick_list_filter,
		};
	}

	set_actions() {
		if (this.in_customize_mode) return;

		this.setup_add_new_button();
		this.setup_refresh_list_button();
		this.setup_filter_list_button();
	}

	setup_add_new_button() {
		this.add_new_button = $(
			`

				${frappe.utils.icon("add", "sm")}

`
		);

		this.add_new_button.appendTo(this.action_area);
		this.add_new_button.on("click", () => {
			frappe.set_route(
				frappe.utils.generate_route({
					type: "doctype",
					name: this.document_type,
					doc_view: "New",
				})
			);
		});
	}

	setup_refresh_list_button() {
		this.refresh_list = $(
			`

				${frappe.utils.icon("refresh", "sm")}

`
		);

		this.refresh_list.appendTo(this.action_area);
		this.refresh_list.on("click", () => {
			this.body.empty();
			this.set_body();
		});
	}

	setup_filter_list_button() {
		this.filter_list = $(
			`

				${frappe.utils.icon("filter", "sm")}

`
		);

		this.filter_list.appendTo(this.action_area);
		this.filter_list.on("click", () => this.setup_filter_dialog());
	}

	setup_filter(doctype) {
		if (this.filter_group) {
			this.filter_group.wrapper.empty();
			delete this.filter_group;
		}

		this.filters = frappe.utils.get_filter_from_json(this.quick_list_filter, doctype);

		this.filter_group = new frappe.ui.FilterGroup({
			parent: this.dialog.get_field("filter_area").$wrapper,
			doctype: doctype,
			on_change: () => {},
		});

		frappe.model.with_doctype(doctype, () => {
			this.filter_group.add_filters_to_filter_group(this.filters);
			this.dialog.set_df_property("filter_area", "hidden", false);
		});
	}

	setup_filter_dialog() {
		let fields = [
			{
				fieldtype: "HTML",
				fieldname: "filter_area",
			},
		];
		let me = this;
		this.dialog = new frappe.ui.Dialog({
			title: __("Set Filters for {0}", [__(this.document_type)]),
			fields: fields,
			primary_action: function () {
				let old_filter = me.quick_list_filter;
				let filters = me.filter_group.get_filters();
				me.quick_list_filter = frappe.utils.get_filter_as_json(filters);

				this.hide();

				if (old_filter != me.quick_list_filter) {
					me.body.empty();
					me.set_footer();
					me.set_body();
				}
			},
			primary_action_label: __("Set"),
		});

		this.dialog.show();
		this.setup_filter(this.document_type);
	}

	render_loading_state() {
		this.body.empty();
		this.loading = $(`<div class="list-loading-state text-muted">${__("Loading...")}</div>`);
		this.loading.appendTo(this.body);
	}

	render_no_data_state() {
		this.loading = $(`<div class="list-no-data-state text-muted">${__("No Data...")}</div>`);
		this.loading.appendTo(this.body);
	}

	setup_quick_list_item(doc) {
		const indicator = frappe.get_indicator(doc, this.document_type);

		let $quick_list_item = $(`

						${strip_html(doc[this.title_field_name])}

						${frappe.datetime.prettyDate(doc.modified)}

		`);

		if (indicator) {
			$(`

					${__(indicator[0])}

			`).appendTo($quick_list_item);
		}

		$(`<div class="right-arrow">${frappe.utils.icon("right", "xs")}</div>`).appendTo(
			$quick_list_item
		);

		$quick_list_item.click(() => {
			frappe.set_route(`${frappe.utils.get_form_link(this.document_type, doc.name)}`);
		});

		return $quick_list_item;
	}

	set_body() {
		this.widget.addClass("quick-list-widget-box");

		this.render_loading_state();

		frappe.model.with_doctype(this.document_type, () => {
			let fields = ["name"];

			// get name of title field
			if (!this.title_field_name) {
				let meta = frappe.get_meta(this.document_type);
				this.title_field_name = (meta && meta.title_field) || "name";
			}

			if (this.title_field_name && this.title_field_name != "name") {
				fields.push(this.title_field_name);
			}

			// check doctype has status field
			this.has_status_field = frappe.meta.has_field(this.document_type, "status");

			if (this.has_status_field) {
				fields.push("status");
				fields.push("docstatus");

				// add workflow state field if workflow exist & is active
				let workflow_fieldname = frappe.workflow.get_state_fieldname(this.document_type);
				workflow_fieldname && fields.push(workflow_fieldname);
			}

			fields.push("modified");

			let quick_list_filter = frappe.utils.get_filter_from_json(this.quick_list_filter);

			let args = {
				method: "frappe.desk.reportview.get",
				args: {
					doctype: this.document_type,
					fields: fields,
					filters: quick_list_filter,
					order_by: "modified desc",
					start: 0,
					page_length: 4,
				},
			};

			frappe.call(args).then((r) => {
				if (!r.message) return;
				let data = r.message;

				this.body.empty();
				data = !Array.isArray(data) ? frappe.utils.dict(data.keys, data.values) : data;

				if (!data.length) {
					this.render_no_data_state();
					return;
				}

				this.quick_list = data.map((doc) => this.setup_quick_list_item(doc));
				this.quick_list.forEach(($quick_list_item) =>
					$quick_list_item.appendTo(this.body)
				);
			});
		});
	}

	set_footer() {
		this.footer.empty();

		let filters = frappe.utils.get_filter_from_json(this.quick_list_filter);
		if (filters) {
			frappe.route_options = filters;
		}
		let route = frappe.utils.generate_route({ type: "doctype", name: this.document_type });
		this.see_all_button = $(`
			${__("View List")}
		`).appendTo(this.footer);
	}
}
<commit_msg>style: whitespace<commit_after>import Widget from "./base_widget.js";

frappe.provide("frappe.utils");

export default class QuickListWidget extends Widget {
	constructor(opts) {
		opts.shadow = true;
		super(opts);
	}

	get_config() {
		return {
			document_type: this.document_type,
			label: this.label,
			quick_list_filter: this.quick_list_filter,
		};
	}

	set_actions() {
		if (this.in_customize_mode) return;

		this.setup_add_new_button();
		this.setup_refresh_list_button();
		this.setup_filter_list_button();
	}

	setup_add_new_button() {
		this.add_new_button = $(
			`

				${frappe.utils.icon("add", "sm")}

`
		);

		this.add_new_button.appendTo(this.action_area);
		this.add_new_button.on("click", () => {
			frappe.set_route(
				frappe.utils.generate_route({
					type: "doctype",
					name: this.document_type,
					doc_view: "New",
				})
			);
		});
	}

	setup_refresh_list_button() {
		this.refresh_list = $(
			`

				${frappe.utils.icon("refresh", "sm")}

`
		);

		this.refresh_list.appendTo(this.action_area);
		this.refresh_list.on("click", () => {
			this.body.empty();
			this.set_body();
		});
	}

	setup_filter_list_button() {
		this.filter_list = $(
			`

				${frappe.utils.icon("filter", "sm")}

`
		);

		this.filter_list.appendTo(this.action_area);
		this.filter_list.on("click", () => this.setup_filter_dialog());
	}

	setup_filter(doctype) {
		if (this.filter_group) {
			this.filter_group.wrapper.empty();
			delete this.filter_group;
		}

		this.filters = frappe.utils.get_filter_from_json(this.quick_list_filter, doctype);

		this.filter_group = new frappe.ui.FilterGroup({
			parent: this.dialog.get_field("filter_area").$wrapper,
			doctype: doctype,
			on_change: () => {},
		});

		frappe.model.with_doctype(doctype, () => {
			this.filter_group.add_filters_to_filter_group(this.filters);
			this.dialog.set_df_property("filter_area", "hidden", false);
		});
	}

	setup_filter_dialog() {
		let fields = [
			{
				fieldtype: "HTML",
				fieldname: "filter_area",
			},
		];
		let me = this;
		this.dialog = new frappe.ui.Dialog({
			title: __("Set Filters for {0}", [__(this.document_type)]),
			fields: fields,
			primary_action: function () {
				let old_filter = me.quick_list_filter;
				let filters = me.filter_group.get_filters();
				me.quick_list_filter = frappe.utils.get_filter_as_json(filters);

				this.hide();

				if (old_filter != me.quick_list_filter) {
					me.body.empty();
					me.set_footer();
					me.set_body();
				}
			},
			primary_action_label: __("Set"),
		});

		this.dialog.show();
		this.setup_filter(this.document_type);
	}

	render_loading_state() {
		this.body.empty();
		this.loading = $(`<div class="list-loading-state text-muted">${__("Loading...")}</div>`);
		this.loading.appendTo(this.body);
	}

	render_no_data_state() {
		this.loading = $(`<div class="list-no-data-state text-muted">${__("No Data...")}</div>`);
		this.loading.appendTo(this.body);
	}

	setup_quick_list_item(doc) {
		const indicator = frappe.get_indicator(doc, this.document_type);

		let $quick_list_item = $(`

						${strip_html(doc[this.title_field_name])}

						${frappe.datetime.prettyDate(doc.modified)}

		`);

		if (indicator) {
			$(`

					${__(indicator[0])}

			`).appendTo($quick_list_item);
		}

		$(`<div class="right-arrow">${frappe.utils.icon("right", "xs")}</div>`).appendTo(
			$quick_list_item
		);

		$quick_list_item.click(() => {
			frappe.set_route(`${frappe.utils.get_form_link(this.document_type, doc.name)}`);
		});

		return $quick_list_item;
	}

	set_body() {
		this.widget.addClass("quick-list-widget-box");

		this.render_loading_state();

		frappe.model.with_doctype(this.document_type, () => {
			let fields = ["name"];

			// get name of title field
			if (!this.title_field_name) {
				let meta = frappe.get_meta(this.document_type);
				this.title_field_name = (meta && meta.title_field) || "name";
			}

			if (this.title_field_name && this.title_field_name != "name") {
				fields.push(this.title_field_name);
			}

			// check doctype has status field
			this.has_status_field = frappe.meta.has_field(this.document_type, "status");

			if (this.has_status_field) {
				fields.push("status");
				fields.push("docstatus");

				// add workflow state field if workflow exist & is active
				let workflow_fieldname = frappe.workflow.get_state_fieldname(this.document_type);
				workflow_fieldname && fields.push(workflow_fieldname);
			}

			fields.push("modified");

			let quick_list_filter = frappe.utils.get_filter_from_json(this.quick_list_filter);

			let args = {
				method: "frappe.desk.reportview.get",
				args: {
					doctype: this.document_type,
					fields: fields,
					filters: quick_list_filter,
					order_by: "modified desc",
					start: 0,
					page_length: 4,
				},
			};

			frappe.call(args).then((r) => {
				if (!r.message) return;
				let data = r.message;

				this.body.empty();
				data = !Array.isArray(data) ? frappe.utils.dict(data.keys, data.values) : data;

				if (!data.length) {
					this.render_no_data_state();
					return;
				}

				this.quick_list = data.map((doc) => this.setup_quick_list_item(doc));
				this.quick_list.forEach(($quick_list_item) =>
					$quick_list_item.appendTo(this.body)
				);
			});
		});
	}

	set_footer() {
		this.footer.empty();

		let filters = frappe.utils.get_filter_from_json(this.quick_list_filter);
		if (filters) {
			frappe.route_options = filters;
		}
		let route = frappe.utils.generate_route({ type: "doctype", name: this.document_type });
		this.see_all_button = $(`
			${__("View List")}
		`).appendTo(this.footer);
	}
}
<|endoftext|>


<commit_before>Accounts.onCreateUser(function (options, user) {
    user['profile'] = options.profile;
    user['totalPoints'] = 0;
    user['commentPoints'] = 0;
    user['postPoints'] = 0;
    user['achievements'] = [];
    user['challenges'] = [];
    return user;
});
<commit_msg>users will have a 'usablePoints' (equals to zero) on their documents on creation<commit_after>Accounts.onCreateUser(function (options, user) {
    user['profile'] = options.profile;
    user['totalPoints'] = 0;
    user['commentPoints'] = 0;
    user['postPoints'] = 0;
    user['achievements'] = [];
    user['usablePoints'] = 0;
    user['challenges'] = [];
    return user;
});
<|endoftext|>


<commit_before>/*global window, console, clearInterval, setInterval, document, unescape, L, webkitURL*/
/*
 * VideoPlayer represents a Lynckia video component that shows either a local or a remote video.
 * Ex.: var player = VideoPlayer({id: id, stream: stream, elementID: elementID});
 * A VideoPlayer is also a View component.
 */
var Erizo = Erizo || {};
Erizo.VideoPlayer = function (spec) {
    "use strict";

    var that = Erizo.View({}),
        onmouseover,
        onmouseout;

    // Variables

    // VideoPlayer ID
    that.id = spec.id;

    // Stream that the VideoPlayer will play
    that.stream = spec.stream.stream;

    // DOM element in which the VideoPlayer will be appended
    that.elementID = spec.elementID;

    // Private functions
    onmouseover = function (evt) {
        that.bar.display();
    };

    onmouseout = function (evt) {
        that.bar.hide();
    };

    // Public functions

    // It will stop the VideoPlayer and remove it from the HTML
    that.destroy = function () {
        that.video.pause();
        clearInterval(that.resize);
        that.parentNode.removeChild(that.div);
    };

    window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
        document.getElementById(key).value = unescape(value);
    });

    L.Logger.debug('Creating URL from stream ' + that.stream);
    that.stream_url = webkitURL.createObjectURL(that.stream);

    // Container
    that.div = document.createElement('div');
    that.div.setAttribute('id', 'player_' + that.id);
    that.div.setAttribute('style', 'width: 100%; height: 100%; position: relative; background-color: black; overflow: hidden;');

    // Loader icon
    that.loader = document.createElement('img');
    that.loader.setAttribute('style', 'width: 16px; height: 16px; position: absolute; top: 50%; left: 50%; margin-top: -8px; margin-left: -8px');
    that.loader.setAttribute('id', 'back_' + that.id);
    that.loader.setAttribute('src', that.url + '/assets/loader.gif');

    // Video tag
    that.video = document.createElement('video');
    that.video.setAttribute('id', 'stream' + that.id);
    that.video.setAttribute('style', 'width: 100%; height: 100%; position: absolute');
    that.video.setAttribute('autoplay', 'autoplay');

    if (that.elementID !== undefined) {
        document.getElementById(that.elementID).appendChild(that.div);
        that.container = document.getElementById(that.elementID);
    } else {
        document.body.appendChild(that.div);
        that.container = document.body;
    }

    that.parentNode = that.div.parentNode;

    that.div.appendChild(that.loader);
    that.div.appendChild(that.video);

    that.containerWidth = 0;
    that.containerHeight = 0;

    that.resize = setInterval(function () {

        var width = that.container.offsetWidth,
            height = that.container.offsetHeight;

        if (width !== that.containerWidth || height !== that.containerHeight) {

            if (width * (3 / 4) > height) {

                that.video.style.width = width + "px";
                that.video.style.height = (3 / 4) * width + "px";

                that.video.style.top = -((3 / 4) * width / 2 - height / 2) + "px";
                that.video.style.left = "0px";

            } else {

                that.video.style.height = height + "px";
                that.video.style.width = (4 / 3) * height + "px";

                that.video.style.left = -((4 / 3) * height / 2 - width / 2) + "px";
                that.video.style.top = "0px";

            }

            that.containerWidth = width;
            that.containerHeight = height;
        }

    }, 500);

    // Bottom Bar
    that.bar = new Erizo.Bar({elementID: 'player_' + that.id, id: that.id, stream: spec.stream, video: that.video, options: spec.options});

    that.div.onmouseover = onmouseover;
    that.div.onmouseout = onmouseout;

    that.video.src = that.stream_url;

    return that;
};<commit_msg>Resolved a bug in VideoPlayer<commit_after>/*global window, console, clearInterval, setInterval, document, unescape, L, webkitURL*/
/*
 * VideoPlayer represents a Lynckia video component that shows either a local or a remote video.
 * Ex.: var player = VideoPlayer({id: id, stream: stream, elementID: elementID});
 * A VideoPlayer is also a View component.
 */
var Erizo = Erizo || {};
Erizo.VideoPlayer = function (spec) {
    "use strict";

    var that = Erizo.View({}),
        onmouseover,
        onmouseout;

    // Variables

    // VideoPlayer ID
    that.id = spec.id;

    // Stream that the VideoPlayer will play
    that.stream = spec.stream.stream;

    // DOM element in which the VideoPlayer will be appended
    that.elementID = spec.elementID;

    // Private functions
    onmouseover = function (evt) {
        that.bar.display();
    };

    onmouseout = function (evt) {
        that.bar.hide();
    };

    // Public functions

    // It will stop the VideoPlayer and remove it from the HTML
    that.destroy = function () {
        that.video.pause();
        clearInterval(that.resize);
        that.parentNode.removeChild(that.div);
    };

    /*window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
        document.getElementById(key).value = unescape(value);
    });*/

    L.Logger.debug('Creating URL from stream ' + that.stream);
    that.stream_url = webkitURL.createObjectURL(that.stream);

    // Container
    that.div = document.createElement('div');
    that.div.setAttribute('id', 'player_' + that.id);
    that.div.setAttribute('style', 'width: 100%; height: 100%; position: relative; background-color: black; overflow: hidden;');

    // Loader icon
    that.loader = document.createElement('img');
    that.loader.setAttribute('style', 'width: 16px; height: 16px; position: absolute; top: 50%; left: 50%; margin-top: -8px; margin-left: -8px');
    that.loader.setAttribute('id', 'back_' + that.id);
    that.loader.setAttribute('src', that.url + '/assets/loader.gif');

    // Video tag
    that.video = document.createElement('video');
    that.video.setAttribute('id', 'stream' + that.id);
    that.video.setAttribute('style', 'width: 100%; height: 100%; position: absolute');
    that.video.setAttribute('autoplay', 'autoplay');

    if (that.elementID !== undefined) {
        document.getElementById(that.elementID).appendChild(that.div);
        that.container = document.getElementById(that.elementID);
    } else {
        document.body.appendChild(that.div);
        that.container = document.body;
    }

    that.parentNode = that.div.parentNode;

    that.div.appendChild(that.loader);
    that.div.appendChild(that.video);

    that.containerWidth = 0;
    that.containerHeight = 0;

    that.resize = setInterval(function () {

        var width = that.container.offsetWidth,
            height = that.container.offsetHeight;

        if (width !== that.containerWidth || height !== that.containerHeight) {

            if (width * (3 / 4) > height) {

                that.video.style.width = width + "px";
                that.video.style.height = (3 / 4) * width + "px";

                that.video.style.top = -((3 / 4) * width / 2 - height / 2) + "px";
                that.video.style.left = "0px";

            } else {

                that.video.style.height = height + "px";
                that.video.style.width = (4 / 3) * height + "px";

                that.video.style.left = -((4 / 3) * height / 2 - width / 2) + "px";
                that.video.style.top = "0px";

            }

            that.containerWidth = width;
            that.containerHeight = height;
        }

    }, 500);

    // Bottom Bar
    that.bar = new Erizo.Bar({elementID: 'player_' + that.id, id: that.id, stream: spec.stream, video: that.video, options: spec.options});

    that.div.onmouseover = onmouseover;
    that.div.onmouseout = onmouseout;

    that.video.src = that.stream_url;

    return that;
};<|endoftext|>