<commit_before>Jedis = this.Jedis || {};
Meteor.startup( function() {
	var settings;
	var directoryService;
	var users = [];
	var addToGeneralInterval;

	Meteor.users.find().observe({
		added: addUserToLocationChannel,
		changed: updateUserLocationChannel,
		removed: removeUserFromLocationChannel
		}
	)

	console.log("Loading Default System Settings");
	try {
		// JSON.parse is very syntax sensitive.  e.g. trailing comma with no following value
	 	// will cause an error.
	 	settings = JSON.parse(Assets.getText('defaultSettings.json')) || {};
		defineSettings(settings);

	} catch(err) {
	 	console.log('Error loading default settings: ' + err.message);
	}

	directoryService = new DirectoryService(settings.ldap);
	Jedis.accessManager = new AccessManager(directoryService);
	Jedis.accessManager.loadAccessPermissions();

	Jedis.accountManager = new AccountManager(directoryService);
	Jedis.accountManager.loadUsers();
	adminUserId = settings.mac.adminUsername;
	if( adminUserId ) {
		console.log('Set ' + adminUserId + ' as admin');
		Jedis.accountManager.setAdmin(adminUserId);
	}
	// need to add users to the 'GENERAL' channel (created in initialData), but
	// it may not have been created yet.  So we need to periodically test if it
	// exists then add them when it does.
	// !! the delay value has to be long enough to account for adding all the users
	// otherwise it may try to re-insert the user into general
	addToGeneralInterval = Meteor.setInterval( function() {
		var room = ChatRoom.findOne({_id:'GENERAL'})
		if( room ) {
			// returns non-jedis users that will be added to GENERAL room if they aren't already added
			users = Meteor.users.find().fetch();

			// based on setUsername.coffee that adds uesrs after registration.  We can't reuse it because
			// it checks Meteor.userId which doesn't apply to what we're doing
			addUsersToRoom(users, 'GENERAL', false);
			Meteor.clearInterval(addToGeneralInterval);
		}
	}, 10000)

	// Register our custom login manager that authenticates via LDAP with Meteor's accounts package
	Accounts.registerLoginHandler(Jedis.accountManager.authId, Jedis.accountManager.loginHandler);
});

var addUsersToLocation = function() {
	var owner = Meteor.users.findOne({_id:'testadmin'});
	var rawUsers = Meteor.users.rawCollection();
	var pipeline = [{'$group': {_id:'$profile.location', usernames: {$push : "$username"}}}]
	Meteor.wrapAsync( rawUsers.aggregate, rawUsers)(pipeline, function(err, usersByLocation) {
		if( err ) {
			console.log( err )
		} else {
			usersByLocation.forEach(function(location) {
				var channel = ChatRoom.findOne({name:location._id, t:'c'});
				if( channel ) {
					// location exists so add user if they don't already belong
					addUsersToRoom(location.usernames, channel._id, false)
				} else {
					// location doesn't exist so create new channel with users
					createChannel(owner, location._id, location.usernames);
				}
			})
		}

	})
}

var addUserToLocationChannel = function(user) {
	var channel;
	var chId;
	if( _.isUndefined(user.profile) || _.isUndefined(user.profile.location) ) {
		console.log('User missing location in profile')
		return
	}
	location = user.profile.location
	slugLocation = _.slugify(location)
	channel = ChatRoom.findOne({name:slugLocation, t:'c'})
	if( _.isUndefined(channel) ) {
		chId = createChannel(slugLocation,location, [user.username]);
	} else {
		chId = channel._id;
	}
	addUsersToRoom( [user], chId, false)
}

var updateUserLocationChannel = function(newUser, oldUser) {
	var oldLocation = '';
	var newLocation = '';

	if( !_.isUndefined(oldUser.profile) && !_.isUndefined(oldUser.profile.location)) {
		oldLocation = oldUser.profile.location;
	}
	if( !_.isUndefined(newUser.profile) && !_.isUndefined(newUser.profile.location)) {
		newLocation = newUser.profile.location;
	}
	if( oldLocation === newLocation ) {
		return
	}

	removeUserFromLocationChannel(oldUser);
	addUserToLocationChannel(newUser);
}

var removeUserFromLocationChannel = function(user) {
	// similar to removeUserFromRoom.coffee, but we don't use the currently logged
	// in user
	if( _.isUndefined(user.profile) || _.isUndefined(user.profile.location) ) {
		console.log('User missing location in profile')
		return
	}
	console.log('remove user from location: ' + user.profile.location);
	room = ChatRoom.findOne({name: user.profile.location});
	if( _.isUndefined(room) ) {
		console.log('Unable to remove ' + user.username + ' from old location ' + user.profile.location + ' because it was not found.')
		return;
	}
	if (room.t !== 'c') {
		throw new Meteor.Error(403, 'Not allowed');
	}

	ChatRoom.update({_id:room._id}, {$pull: {usernames: user.username}});

	ChatSubscription.remove({ 'u._id': user.username, rid: room._id });

	/*
	ChatMessage.insert
		rid: room._id
		ts: (new Date)
		t: 'ru'
		msg: user.name
		u:
			_id: Meteor.userId()
			username: Meteor.user().username
	*/
}

var addUsersToRoom = function( users, roomId, createJoinedMessage) {
	var now = new Date();
	var room = ChatRoom.findOne({_id: roomId})
	if( ! room ) {
		console.log( 'Room with id: ' + roomId + ' not found');
		return
	}
	// add usernames to specified room and create subscription.
	users.forEach( function( user ) {

		if( ! ChatSubscription.findOne({rid: roomId, 'u._id' : user._id }) ) {
			// Non-existant ChatSubscription implies user missing from ChatRoom
			ChatRoom.update( {_id: roomId },
				{
					// can't use addToSet because sort doesn't work.
					$push :
					{ usernames :
						{
						$each : [user.username],
						$sort : 1
						}
					}
				});

			ChatSubscription.insert( {
				rid: roomId,
				name: room.name,
				displayName: room.displayName,
				ts: now,
				t: room.t,
				f: true,
				open: true,
				alert: false,
				unread : createJoinedMessage ? 1 : 0,
				u: { _id : user._id, username : user.username }
			});

			if( createJoinedMessage ) {
				ChatMessage.insert({
					rid: roomId,
					ts: now,
					t: 'uj',
					msg : '',
				u: { _id : user._id, username : user.username }
				})
			}

			console.log('Added ' + user.username + ' to room ' + room.name);
		}
	});
}

var createChannel = function(name, displayName, members) {
	// the same as createChannel method, except it doesn't check for logged in user
	if( !(/^[0-9a-z-_\s.]+$/i).test(name)) {
		throw new Meteor.Error( 'name-invalid', 'Channel name is invalid' );
	}

	var now = new Date()

	// avoid duplicate names
	if (ChatRoom.findOne({name:name})) {
		throw new Meteor.Error ('duplicate-name', 'Channel name exists')
	}

	console.log('Creating new channel: ' + name);

	room = {
		usernames: members,
		ts: now,
		t: 'c',
		name: name,
		displayName: displayName,
		msgs: 0,
		accessPermissions: Jedis.channelPermissions(),
		securityLabel : Jedis.legacyLabel(Jedis.channelPermissions())
	}

	//RocketChat.callbacks.run('beforeCreateChannel', owner, room);

	// create new room
	var rid = ChatRoom.insert( room )

	members.forEach(function(username) {
		member = Meteor.users.findOne({username: username})
		if (member) {

			sub = {
				rid: rid,
				ts: now,
				name: name,
				displayName: displayName,
				t: 'c',
				f: true,
				unread: 0,
				u: {
					_id: member._id,
					username: username
				},
				ls  : now,
				open : true,
				alert : false
			}

			ChatSubscription.insert (sub);
		}
	});

	/*
	Meteor.defer(function() {
		RocketChat.callbacks.run( 'afterCreateChannel', owner, room);
	});
	 */

	return rid;
}

var defineSettings = function(config) {
	// NOTE: initial values do NOT overwrite existing values. You have to use the admin UI to modify the setting
	// once it exists in the collection
	RocketChat.settings.addGroup( 'MAC');
	// NOTE RocketChat only supports string and boolean values.
	RocketChat.settings.add('Network_Classification', config.mac.networkClassification, { type: 'string', group: 'MAC', public: true });
	RocketChat.settings.add('System_CountryCode', config.mac.systemCountryCode, { type: 'string', group: 'MAC', public: true });
	RocketChat.settings.add('Admin U', config.mac.adminUsername, { type: 'string', group: 'MAC', public: true });

	RocketChat.settings.addGroup( 'LDAP');
	RocketChat.settings.add('url', config.ldap.url, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('userSearchBaseDNTemplate', config.ldap.userSearchBaseDNTemplate, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('adminBaseDN', config.ldap.admin.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('adminCredentials', config.ldap.admin.credentials, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsBaseDN', config.ldap.accessDefs.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsFilter', config.ldap.accessDefs.opts.filter, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsScope', config.ldap.accessDefs.opts.scope, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersBaseDN', config.ldap.users.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersFilter', config.ldap.users.opts.filter, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersScope', config.ldap.users.opts.scope, { type: 'string', group: 'LDAP', public: false });
}

<commit_msg>Removed LDAP and admin username configuration settings from the UI because they require a system restart and it doesn't make sense to save them in the db.<commit_after>Jedis = this.Jedis || {};
Meteor.startup( function() {
	var settings;
	var directoryService;
	var users = [];
	var addToGeneralInterval;

	Meteor.users.find().observe({
		added: addUserToLocationChannel,
		changed: updateUserLocationChannel,
		removed: removeUserFromLocationChannel
		}
	)

	console.log("Loading Default System Settings");
	try {
		// JSON.parse is very syntax sensitive.  e.g. trailing comma with no following value
	 	// will cause an error.
	 	settings = JSON.parse(Assets.getText('defaultSettings.json')) || {};
		defineSettings(settings);

	} catch(err) {
	 	console.log('Error loading default settings: ' + err.message);
	}

	directoryService = new DirectoryService(settings.ldap);
	Jedis.accessManager = new AccessManager(directoryService);
	Jedis.accessManager.loadAccessPermissions();

	Jedis.accountManager = new AccountManager(directoryService);
	Jedis.accountManager.loadUsers();
	adminUserId = settings.mac.adminUsername;
	if( adminUserId ) {
		console.log('Set ' + adminUserId + ' as admin');
		Jedis.accountManager.setAdmin(adminUserId);
	}
	// need to add users to the 'GENERAL' channel (created in initialData), but
	// it may not have been created yet.  So we need to periodically test if it
	// exists then add them when it does.
	// !! the delay value has to be long enough to account for adding all the users
	// otherwise it may try to re-insert the user into general
	addToGeneralInterval = Meteor.setInterval( function() {
		var room = ChatRoom.findOne({_id:'GENERAL'})
		if( room ) {
			// returns non-jedis users that will be added to GENERAL room if they aren't already added
			users = Meteor.users.find().fetch();

			// based on setUsername.coffee that adds uesrs after registration.  We can't reuse it because
			// it checks Meteor.userId which doesn't apply to what we're doing
			addUsersToRoom(users, 'GENERAL', false);
			Meteor.clearInterval(addToGeneralInterval);
		}
	}, 10000)

	// Register our custom login manager that authenticates via LDAP with Meteor's accounts package
	Accounts.registerLoginHandler(Jedis.accountManager.authId, Jedis.accountManager.loginHandler);
});

var addUsersToLocation = function() {
	var owner = Meteor.users.findOne({_id:'testadmin'});
	var rawUsers = Meteor.users.rawCollection();
	var pipeline = [{'$group': {_id:'$profile.location', usernames: {$push : "$username"}}}]
	Meteor.wrapAsync( rawUsers.aggregate, rawUsers)(pipeline, function(err, usersByLocation) {
		if( err ) {
			console.log( err )
		} else {
			usersByLocation.forEach(function(location) {
				var channel = ChatRoom.findOne({name:location._id, t:'c'});
				if( channel ) {
					// location exists so add user if they don't already belong
					addUsersToRoom(location.usernames, channel._id, false)
				} else {
					// location doesn't exist so create new channel with users
					createChannel(owner, location._id, location.usernames);
				}
			})
		}

	})
}

var addUserToLocationChannel = function(user) {
	var channel;
	var chId;
	if( _.isUndefined(user.profile) || _.isUndefined(user.profile.location) ) {
		console.log('User missing location in profile')
		return
	}
	location = user.profile.location
	slugLocation = _.slugify(location)
	channel = ChatRoom.findOne({name:slugLocation, t:'c'})
	if( _.isUndefined(channel) ) {
		chId = createChannel(slugLocation,location, [user.username]);
	} else {
		chId = channel._id;
	}
	addUsersToRoom( [user], chId, false)
}

var updateUserLocationChannel = function(newUser, oldUser) {
	var oldLocation = '';
	var newLocation = '';

	if( !_.isUndefined(oldUser.profile) && !_.isUndefined(oldUser.profile.location)) {
		oldLocation = oldUser.profile.location;
	}
	if( !_.isUndefined(newUser.profile) && !_.isUndefined(newUser.profile.location)) {
		newLocation = newUser.profile.location;
	}
	if( oldLocation === newLocation ) {
		return
	}

	removeUserFromLocationChannel(oldUser);
	addUserToLocationChannel(newUser);
}

var removeUserFromLocationChannel = function(user) {
	// similar to removeUserFromRoom.coffee, but we don't use the currently logged
	// in user
	if( _.isUndefined(user.profile) || _.isUndefined(user.profile.location) ) {
		console.log('User missing location in profile')
		return
	}
	console.log('remove user from location: ' + user.profile.location);
	room = ChatRoom.findOne({name: user.profile.location});
	if( _.isUndefined(room) ) {
		console.log('Unable to remove ' + user.username + ' from old location ' + user.profile.location + ' because it was not found.')
		return;
	}
	if (room.t !== 'c') {
		throw new Meteor.Error(403, 'Not allowed');
	}

	ChatRoom.update({_id:room._id}, {$pull: {usernames: user.username}});

	ChatSubscription.remove({ 'u._id': user.username, rid: room._id });

	/*
	ChatMessage.insert
		rid: room._id
		ts: (new Date)
		t: 'ru'
		msg: user.name
		u:
			_id: Meteor.userId()
			username: Meteor.user().username
	*/
}

var addUsersToRoom = function( users, roomId, createJoinedMessage) {
	var now = new Date();
	var room = ChatRoom.findOne({_id: roomId})
	if( ! room ) {
		console.log( 'Room with id: ' + roomId + ' not found');
		return
	}
	// add usernames to specified room and create subscription.
	users.forEach( function( user ) {

		if( ! ChatSubscription.findOne({rid: roomId, 'u._id' : user._id }) ) {
			// Non-existant ChatSubscription implies user missing from ChatRoom
			ChatRoom.update( {_id: roomId },
				{
					// can't use addToSet because sort doesn't work.
					$push :
					{ usernames :
						{
						$each : [user.username],
						$sort : 1
						}
					}
				});

			ChatSubscription.insert( {
				rid: roomId,
				name: room.name,
				displayName: room.displayName,
				ts: now,
				t: room.t,
				f: true,
				open: true,
				alert: false,
				unread : createJoinedMessage ? 1 : 0,
				u: { _id : user._id, username : user.username }
			});

			if( createJoinedMessage ) {
				ChatMessage.insert({
					rid: roomId,
					ts: now,
					t: 'uj',
					msg : '',
				u: { _id : user._id, username : user.username }
				})
			}

			console.log('Added ' + user.username + ' to room ' + room.name);
		}
	});
}

var createChannel = function(name, displayName, members) {
	// the same as createChannel method, except it doesn't check for logged in user
	if( !(/^[0-9a-z-_\s.]+$/i).test(name)) {
		throw new Meteor.Error( 'name-invalid', 'Channel name is invalid' );
	}

	var now = new Date()

	// avoid duplicate names
	if (ChatRoom.findOne({name:name})) {
		throw new Meteor.Error ('duplicate-name', 'Channel name exists')
	}

	console.log('Creating new channel: ' + name);

	room = {
		usernames: members,
		ts: now,
		t: 'c',
		name: name,
		displayName: displayName,
		msgs: 0,
		accessPermissions: Jedis.channelPermissions(),
		securityLabel : Jedis.legacyLabel(Jedis.channelPermissions())
	}

	//RocketChat.callbacks.run('beforeCreateChannel', owner, room);

	// create new room
	var rid = ChatRoom.insert( room )

	members.forEach(function(username) {
		member = Meteor.users.findOne({username: username})
		if (member) {

			sub = {
				rid: rid,
				ts: now,
				name: name,
				displayName: displayName,
				t: 'c',
				f: true,
				unread: 0,
				u: {
					_id: member._id,
					username: username
				},
				ls  : now,
				open : true,
				alert : false
			}

			ChatSubscription.insert (sub);
		}
	});

	/*
	Meteor.defer(function() {
		RocketChat.callbacks.run( 'afterCreateChannel', owner, room);
	});
	 */

	return rid;
}

var defineSettings = function(config) {
	// NOTE: initial values do NOT overwrite existing values. You have to use the admin UI to modify the setting
	// once it exists in the collection
	RocketChat.settings.addGroup( 'MAC');
	// NOTE RocketChat only supports string and boolean values.
	RocketChat.settings.add('Network_Classification', config.mac.networkClassification, { type: 'string', group: 'MAC', public: true });
	RocketChat.settings.add('System_CountryCode', config.mac.systemCountryCode, { type: 'string', group: 'MAC', public: true });

	/*
	// It doesn't make sense to configure these settings through the UI because they are read in at startup
	// and require a system restart to take effect
	RocketChat.settings.add('Admin Username', config.mac.adminUsername, { type: 'string', group: 'MAC', public: true });

	RocketChat.settings.addGroup( 'LDAP');
	RocketChat.settings.add('url', config.ldap.url, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('userSearchBaseDNTemplate', config.ldap.userSearchBaseDNTemplate, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('adminBaseDN', config.ldap.admin.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('adminCredentials', config.ldap.admin.credentials, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsBaseDN', config.ldap.accessDefs.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsFilter', config.ldap.accessDefs.opts.filter, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('accessDefsScope', config.ldap.accessDefs.opts.scope, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersBaseDN', config.ldap.users.baseDN, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersFilter', config.ldap.users.opts.filter, { type: 'string', group: 'LDAP', public: false });
	RocketChat.settings.add('usersScope', config.ldap.users.opts.scope, { type: 'string', group: 'LDAP', public: false });
	*/
}

<|endoftext|>


<commit_before>function IssuePage(world, number, organization, repo, callback) {
    var self = this;

    self.browser = world.browser;
    self.issueUrl = "https://github.com/" + organization + "/" + repo + "/issues/" + number;
    self.settings = world.settings;

    self.browser.getAllWindowHandles().then(function (handles) {
        self.handle = handles[0];
    });

    self._navigate().then(callback);
}

IssuePage.prototype._login = function () {
    var self = this;

    self.browser.findElement({name: "login"}).sendKeys(self.settings.GITHUB_USERNAME);
    self.browser.findElement({name: "password"}).sendKeys(self.settings.GITHUB_PASSWORD);
    return self.browser.findElement({name: "commit"}).click();
};

IssuePage.prototype._navigate = function () {
    var self = this;

    self.browser.get(self.issueUrl);

    //it takes a bit for the login and password to drop down
    self.browser.sleep(1000);

    return self.browser.isElementPresent({name: "login"}).then(function (shouldLogin) {
        if (!shouldLogin)
            return;

        return self._login();
    });
};

IssuePage.prototype.isBountyCommentPresent = function () {
    var self = this;

    var xpath = "//a[contains(@href, '" + self.settings.ROOT_URL + "reward/link/')]" +
        "/img[contains(@src, '" + self.settings.ROOT_URL + "reward/image/')]";

    return self.browser.isElementPresent({
        xpath: xpath
    });
};

IssuePage.prototype.openBountyAmount = function () {
    var self = this,
        element = self.browser.findElement({
            xpath: "//span[contains(@class, 'state-indicator open')]"
        });

    return element.getText().then(function (openText) {
        //strip out the number
        return openText.replace(/^\D+/g, "");
    });
};

/**
 * Returns the approval page handle
 */
IssuePage.prototype.postBounty = function (amount) {
    var self = this;

    var bountyInput = self.browser.findElement({id: "bountyInput"});
    bountyInput.clear();
    bountyInput.sendKeys(amount);

    self.browser.findElement({id: "postBounty"}).click();

    return self.browser.getAllWindowHandles().then(function (handles) {
        for (var i = 0; i < handles.length; i++)
            //there should only be two windows open
            //the one that is not this issue page should is the approval page
            if (handles[i] !== self.handle)
                return handles[i];
    });
};

IssuePage.prototype.rewardBounty = function () {
    return this.browser.findElement({id: "rewardBounty"}).click();
};

IssuePage.prototype.switchTo = function () {
    return this.browser.switchTo().window(this.handle);
};

IssuePage.prototype.toggleCurrency = function () {
    return this.browser.findElement({id: "currencyToggle"})
        .findElement({className: "toggle-select"})
        .click();
};

module.exports = {
    IssuePage: IssuePage
};<commit_msg>Make test not picky about root url<commit_after>function IssuePage(world, number, organization, repo, callback) {
    var self = this;

    self.browser = world.browser;
    self.issueUrl = "https://github.com/" + organization + "/" + repo + "/issues/" + number;
    self.settings = world.settings;

    self.browser.getAllWindowHandles().then(function (handles) {
        self.handle = handles[0];
    });

    self._navigate().then(callback);
}

IssuePage.prototype._login = function () {
    var self = this;

    self.browser.findElement({name: "login"}).sendKeys(self.settings.GITHUB_USERNAME);
    self.browser.findElement({name: "password"}).sendKeys(self.settings.GITHUB_PASSWORD);
    return self.browser.findElement({name: "commit"}).click();
};

IssuePage.prototype._navigate = function () {
    var self = this;

    self.browser.get(self.issueUrl);

    //it takes a bit for the login and password to drop down
    self.browser.sleep(1000);

    return self.browser.isElementPresent({name: "login"}).then(function (shouldLogin) {
        if (!shouldLogin)
            return;

        return self._login();
    });
};

IssuePage.prototype.isBountyCommentPresent = function () {
    var self = this;

    var xpath = "//a[contains(@href, 'reward/link/')]/img[contains(@src, 'reward/image/')]";

    return self.browser.isElementPresent({
        xpath: xpath
    });
};

IssuePage.prototype.openBountyAmount = function () {
    var self = this,
        element = self.browser.findElement({
            xpath: "//span[contains(@class, 'state-indicator open')]"
        });

    return element.getText().then(function (openText) {
        //strip out the number
        return openText.replace(/^\D+/g, "");
    });
};

/**
 * Returns the approval page handle
 */
IssuePage.prototype.postBounty = function (amount) {
    var self = this;

    var bountyInput = self.browser.findElement({id: "bountyInput"});
    bountyInput.clear();
    bountyInput.sendKeys(amount);

    self.browser.findElement({id: "postBounty"}).click();

    return self.browser.getAllWindowHandles().then(function (handles) {
        for (var i = 0; i < handles.length; i++)
            //there should only be two windows open
            //the one that is not this issue page should is the approval page
            if (handles[i] !== self.handle)
                return handles[i];
    });
};

IssuePage.prototype.rewardBounty = function () {
    return this.browser.findElement({id: "rewardBounty"}).click();
};

IssuePage.prototype.switchTo = function () {
    return this.browser.switchTo().window(this.handle);
};

IssuePage.prototype.toggleCurrency = function () {
    return this.browser.findElement({id: "currencyToggle"})
        .findElement({className: "toggle-select"})
        .click();
};

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


<commit_before>var Game;

(function() {

/*
 * Game
 * ====
 *
 * The main Game constructor
 */

Game = function() {
    this.Plugins   = new Plugins(this, plugins);

    this.initTime  = null;
    this.loadTime  = null;
    this.startTime = null;
    this.pauseTime = null;
    this.stopTime  = null;

    this.playing   = false;
    this.timer     = null;
    this.frames    = 0;

    this._options = {};

    EventEmitter(this);

    return this;
}

/* Setup Engine */
Game.prototype.init = function() {
    this.emit("beforeinit", [this]);

    this.initTime = this.Utils.time();
    this.Plugins.Init(this);

    // Attach Draw.domElement to Game
    if(this.Draw && this.Draw.domElement) {
        this.domElement = this.Draw.domElement;
    }

    this.emit("init", [this]);
    return this;
}

/* Setup world */
Game.prototype.load = function() {
    if(!this.initTime) {
        this.init();
    }

    this.emit("beforeload", [this]);

    this.loadTime = this.Utils.time();
    this.Plugins.Load(this);

    this.emit("load", [this]);
    return this;
}

/* Start game loop */
Game.prototype.start = function() {
    if(!this.playing) {
        this.startTime = this.Utils.time();
        if(!this.loadTime) {
            this.load();
        }

        this.emit("beforestart", [this]);

        this.timer = this.requestAnimationFrame(this.Loop);
        this.Loop();

        this.emit("start", [this]);
    }

    return this;
}

Game.prototype.pause = function() {
    if(this.playing) {
        this.emit("beforepause", [this]);
        this.pauseTime = this.Utils.time();
        this.cancelAnimationFrame(this.timer);
        this.emit("pause", [this]);
    }
}

Game.prototype.stop = function() {
    if(this.playing) {
        this.emit("beforestop", [this]);
        this.stopTime = this.Utils.time();
        this.cancelAnimationFrame(this.timer);
        this.emit("beforestopreset");
        this.reset();
        this.emit("stop", [this]);
    }

    return this;
}

Game.prototype.Loop = function() {
    this.emit("beforeframe", [this]);
    this.frames++;

    this.emit("beforeupdate", [this]);
    // this.World.Update(this);
    // this.Camera.Update(this);

    this.emit("beforedraw", [this]);
    // this.World.Draw(this);

    this.emit("frame", [this]);
    return this;
}

Game.prototype.Utils = {
    capitalize: function(str) {
        return str.substr(0,1).toUpperCase() + str.substr(1);
    },
    merge: function(first, second, blacklist) {
        if(!blacklist) var blacklist = [];

        for(key in second) {
            if(blacklist.indexOf(key) === -1) {
                first[key] = second[key];
            }
        }

        return first;
    },
    toRadians: function(deg) {
        return (deg * Math.PI) / 180;
    },
    toDegrees: function(rad) {
        return (rad * 180) / Math.PI;
    },
    time: (function() {
        if(performance && performance.now) {
            return function() { return performance.now(); }
        } else if(performance && performance.webkitNow) {
            return function() { return performance.webkitNow(); }
        } else {
            return function() { return Date.now(); }
        }
    })()
}

Game.prototype.options = function(options) {
    this.Utils.merge(this.options, options);

    return this;
}

Game.prototype.plugin = function(plugin) {
    this.Plugins.add(plugin);

    this.emit("plugin", [this, plugin]);
    return this;
}

Game.prototype.plugins = function(plugins) {
    this.Plugins.addMultiple(plugins);

    this.emit("plugins", [this, plugins]);
    return this;
}

Game.prototype.category = function(category) {
    this.Categories.add(category);

    this.emit("category", [this, category]);
    return this;
}

// Add Polyfill HERE!
Game.prototype.requestAnimationFrame = function() {
    this.timer = requestAnimationFrame(this.Loop);
    return this;
}

//Add Polyfill HERE!
Game.prototype.cancelAnimationFrame = function() {
    cancelAnimationFrame(this.timer);
    return this;
}

/*
 * Plugins
 * =======
 *
 * The Plugins constructor
 * Provides the plugin system for Game
 */

var Plugins = function(game) {
    //Save Game for later
    this.game = game;
    this.plugins = {};

    return this;
}

Plugins.prototype.add = function(plugin) {
    if(typeof plugin === "string") {
        // Get the plugin from Game.plugins
        for(var i = 0, len = Game.plugins.length; i < len; i++) {
            if(Game.plugins[i].Name === plugin || Game.plugins[i].prototype.Name === plugin) {
                var plugin = Game.plugins[i];
                break;
            }
        }
        // call new plugin() if it is a constructor
        var plugin = plugin.__noConstructor ? plugin : new plugin(this.game);
    }

    var type = plugin.Type = this.game.Utils.capitalize(plugin.Type);
    var name = plugin.Name;

    //This type is not yet registered
    if(!this.plugins[type]) {
        this.plugins[type] = [];
    }

    //Remove all plugins with the same name
    this.remove(name);
    //Push to plugin pool
    this.plugins[type].push(plugin);

    //Initialize the plugin
    if(this.initTime && plugin.Init) {
        plugin.Init(this.game);
    }
    //Load plugin
    if(this.loadTime && plugin.Load) {
        plugin.Load(this.game);
    }

    //Use the new plugin
    this.use(name);

    return this;
}

Plugins.prototype.addMultiple = function(plugins) {
    for(var i = 0, len = plugins.length; i < len; i++) {
        this.add(plugins[i]);
    }

    return this;
}

Plugins.prototype.remove = function(name) {
    var self = this;

    this.loop(function(plugin, index, array) {
        if(plugin.Name === name) {
            //Remove plugin from plugin list
            array.splice(index, 1);

            var type = plugin.Type;
            if(self.game[type] === plugin) {
                //Remove plugin from game
                self.game[type] = null;
                if(self.plugins[type] && self.plugins[type].length) {
                    //Add last added plugin to the game
                    self.game[type] = self.plugins[type].slice(-1)[0];
                }
            }
        }
    });

    return this;
}

Plugins.prototype.get = function(name, warn) {
    var Plugin = null;

    //Loop through all the plugins and get the right one out
    this.loop(function(plugin, index, array) {
        if(plugin.Name === name) {
            Plugin = plugin;
            return true;
        }
    });

    return Plugin;
}

Plugins.prototype.use = function(name) {
    var plugin = this.get(name);

    //Plugin exists
    if(plugin) {
        var type = plugin.Type;

        this.game[type] = plugin;
        if(plugin.Use) {
            plugin.Use(this.game);
        }
    }

    return this;
}

Plugins.prototype.loop = function(cb) {
    //Loop through types
    outer:
    for(type in this.plugins) {
        var plugins = this.plugins[type];

        //Loop through plugins (per type)
        for(var i = 0; i < plugins.length; i++) {
            var br = cb(plugins[i], i, this.plugins[type]);
            // Break loop if `cb` returns `true` (or another truthy value)
            if(br) { break outer; }
        }
    }

    return this;
}

Plugins.prototype.Init = function() {
    var game = this.game;
    this.loop(function(plugin) {
        if(plugin.Init) {
            plugin.Init(game);
        }
    });

    this.initTime = game.Utils.time();

    return this;
}

Plugins.prototype.Load = function() {
    var game = this.game;
    this.loop(function(plugin) {
        if(plugin.Load) {
            plugin.Load(game);
        }
    });

    this.loadTime = game.Utils.time();

    return this;
}

/*
 * EventEmitter
 *
 * EventEmitter allows for easy event registering and emitting. The API is a copy of the Node.js EventEmitter class.
 */

var EventEmitter = function(obj) {
    if(!obj) obj = this;

    obj.__events = {};
    obj.__allEvents = [];

    obj.addListener = obj.on = function(event, listener) {
        if(!this.__events[event]) this.__events[event] = [];

        if(listener) {
            this.__events[event].push(listener);
        }
        else {
            this.__allEvents.push(event); // event is now the callback
        }

        return this;
    }

    obj.once = function(event, listener) {
        if(!this.__events[event]) this.__events[event] = [];

        if(listener) {
            var func = function() {
                listener.call(null, arguments);
                obj.removeListener(event, func);
            }
            this.__events[event].push(func);
        }
        else {
            var func = function() {
                event.call(null, arguments);
                obj.removeListener(func);
            }
            this.__allEvents.push(func);
        }

        return this;
    }

    obj.emit = function(event, args) {
        if(!args) args = [];
        if(this.__events[event]) {
            var listeners = this.__events[event];
            for(var i = 0, len = listeners.length; i < len; i++) {
                listeners[i].apply(null, args);
            }
        }
        var args = [event].concat(args);
        for(var i = 0, len = this.__allEvents.length; i < len; i++) {
            this.__allEvents[i].apply(null, args);
        }

        return this;
    }

    obj.removeListener = function(event, listener) {
        if(!listener) {
            var listener = event;
            for(event in this.__events) {
                this.removeListener(event, listener);
            }
        }
        else {
            var listeners = this.__events[event];
            if(listeners.indexOf(listener) !== -1) {
                listeners.splice(listeners.indexOf(listener), 1);
            }
            if(this.__allEvents.indexOf(listener) !== -1) {
                this.__allEvents.splice(this.__allEvents.indexOf(listener), 1);
            }
        }

        return this;
    }

    obj.removeAllListeners = function(event) {
        this.__events[event] = [];

        return this;
    }

    obj.listeners = function(event) {
        return this.__events[event] || [];
    }

    return obj;
}

Game.prototype.EventEmitter = EventEmitter;

Game.plugins = [];

/*
 * VARS
 * ====
 *
 * Some variables used  by Game.
 */

    var container = Game.prototype.container = document.createElement("div");
    container.setAttribute("id", "2D-loaders");
    container.setAttribute("style", "width:0;height:0;visibility:hidden;overflow:hidden");
    document.addEventListener("load", function() {
        document.body.appendChild(container);
    });

})();<commit_msg>Tweaked core.js<commit_after>var Game;

(function() {

/*
 * Game
 * ====
 *
 * The main Game constructor
 */

Game = function() {
    this.Plugins   = new Plugins(this, plugins);

    this.initTime  = null;
    this.loadTime  = null;
    this.startTime = null;
    this.pauseTime = null;
    this.stopTime  = null;

    this.playing   = false;
    this.timer     = null;
    this.frames    = 0;
    this.drawTimes = [];

    this._options = {};

    EventEmitter(this);

    return this;
}

/* Setup Engine */
Game.prototype.init = function() {
    this.emit("beforeinit", [this]);

    this.initTime = this.Utils.time();
    this.Plugins.Init(this);

    // Attach Draw.domElement to Game
    if(this.Draw && this.Draw.domElement) {
        this.domElement = this.Draw.domElement;
    }

    this.emit("init", [this]);
    return this;
}

/* Setup world */
Game.prototype.load = function() {
    if(!this.initTime) {
        this.init();
    }

    this.emit("beforeload", [this]);

    this.loadTime = this.Utils.time();
    this.Plugins.Load(this);

    this.emit("load", [this]);
    return this;
}

/* Start game loop */
Game.prototype.start = function() {
    if(!this.playing) {
        this.startTime = this.Utils.time();
        if(!this.loadTime) {
            this.load();
        }

        this.emit("beforestart", [this]);

        this.timer = this.requestAnimationFrame(this.Loop);
        this.playing = true;

        this.emit("start", [this]);
    }

    return this;
}

Game.prototype.pause = function() {
    if(this.playing) {
        this.emit("beforepause", [this]);
        this.pauseTime = this.Utils.time();
        this.cancelAnimationFrame(this.timer);
        this.playing = false;
        this.emit("pause", [this]);
    }
}

Game.prototype.stop = function() {
    if(this.playing) {
        this.emit("beforestop", [this]);
        this.stopTime = this.Utils.time();
        this.cancelAnimationFrame(this.timer);
        this.playing = false;
        this.emit("beforestopreset");
        this.reset();
        this.emit("stop", [this]);
    }

    return this;
}

Game.prototype.Loop = function(game) {
    var START = game.Utils.time();
    game.emit("beforeframe", [game]);
    game.frames++;

    game.emit("beforeupdate", [game]);
    game.Plugins.Update(game);

    game.emit("beforedraw", [game]);
    game.World.Draw(game);

    game.emit("frame", [game]);

    var END = game.Utils.time();
    game.drawTimes.push(END - START);
    return game;
}

Game.prototype.Utils = {
    capitalize: function(str) {
        return str.substr(0,1).toUpperCase() + str.substr(1);
    },
    merge: function(first, second, blacklist) {
        if(!blacklist) var blacklist = [];

        for(key in second) {
            if(blacklist.indexOf(key) === -1) {
                first[key] = second[key];
            }
        }

        return first;
    },
    toRadians: function(deg) {
        return (deg * Math.PI) / 180;
    },
    toDegrees: function(rad) {
        return (rad * 180) / Math.PI;
    },
    time: (function() {
        if(performance && performance.now) {
            return function() { return performance.now(); }
        } else if(performance && performance.webkitNow) {
            return function() { return performance.webkitNow(); }
        } else {
            return function() { return Date.now(); }
        }
    })()
}

Game.prototype.options = function(options) {
    this.Utils.merge(this.options, options);

    return this;
}

Game.prototype.plugin = function(plugin) {
    this.Plugins.add(plugin);

    this.emit("plugin", [this, plugin]);
    return this;
}

Game.prototype.plugins = function(plugins) {
    this.Plugins.addMultiple(plugins);

    this.emit("plugins", [this, plugins]);
    return this;
}

Game.prototype.category = function(category) {
    this.Categories.add(category);

    this.emit("category", [this, category]);
    return this;
}

Game.prototype.getAverageDrawTime = function() {
    var sum = 0;
    var len = this.drawTimes.length;
    for(var i = 0; i < len; i++) {
        sum += this.drawTimes[i];
    }

    return sum / len;
}

// Add Polyfill HERE!
Game.prototype.requestAnimationFrame = function() {
    var game = this;
    var cb = function() {game.Loop(game);}
    this.timer = requestAnimationFrame(cb);
    return this;
}

//Add Polyfill HERE!
Game.prototype.cancelAnimationFrame = function() {
    cancelAnimationFrame(this.timer);
    return this;
}

/*
 * Plugins
 * =======
 *
 * The Plugins constructor
 * Provides the plugin system for Game
 */

var Plugins = function(game) {
    //Save Game for later
    this.game = game;
    this.plugins = {};

    return this;
}

Plugins.prototype.add = function(plugin) {
    if(typeof plugin === "string") {
        // Get the plugin from Game.plugins
        for(var i = 0, len = Game.plugins.length; i < len; i++) {
            if(Game.plugins[i].Name === plugin || Game.plugins[i].prototype.Name === plugin) {
                var plugin = Game.plugins[i];
                break;
            }
        }
        // call new plugin() if it is a constructor
        var plugin = plugin.__noConstructor ? plugin : new plugin(this.game);
    }

    var type = plugin.Type = this.game.Utils.capitalize(plugin.Type);
    var name = plugin.Name;

    //This type is not yet registered
    if(!this.plugins[type]) {
        this.plugins[type] = [];
    }

    //Remove all plugins with the same name
    this.remove(name);
    //Push to plugin pool
    this.plugins[type].push(plugin);

    //Initialize the plugin
    if(this.initTime && plugin.Init) {
        plugin.Init(this.game);
    }
    //Load plugin
    if(this.loadTime && plugin.Load) {
        plugin.Load(this.game);
    }

    //Use the new plugin
    this.use(name);

    return this;
}

Plugins.prototype.addMultiple = function(plugins) {
    for(var i = 0, len = plugins.length; i < len; i++) {
        this.add(plugins[i]);
    }

    return this;
}

Plugins.prototype.remove = function(name) {
    var self = this;

    this.loop(function(plugin, index, array) {
        if(plugin.Name === name) {
            //Remove plugin from plugin list
            array.splice(index, 1);

            var type = plugin.Type;
            if(self.game[type] === plugin) {
                //Remove plugin from game
                self.game[type] = null;
                if(self.plugins[type] && self.plugins[type].length) {
                    //Add last added plugin to the game
                    self.game[type] = self.plugins[type].slice(-1)[0];
                }
            }
        }
    });

    return this;
}

Plugins.prototype.get = function(name, warn) {
    var Plugin = null;

    //Loop through all the plugins and get the right one out
    this.loop(function(plugin, index, array) {
        if(plugin.Name === name) {
            Plugin = plugin;
            return true;
        }
    });

    return Plugin;
}

Plugins.prototype.use = function(name) {
    var plugin = this.get(name);

    //Plugin exists
    if(plugin) {
        var type = plugin.Type;

        this.game[type] = plugin;
        if(plugin.Use) {
            plugin.Use(this.game);
        }
    }

    return this;
}

Plugins.prototype.loop = function(cb) {
    //Loop through types
    outer:
    for(type in this.plugins) {
        var plugins = this.plugins[type];

        //Loop through plugins (per type)
        for(var i = 0; i < plugins.length; i++) {
            var br = cb(plugins[i], i, this.plugins[type]);
            // Break loop if `cb` returns `true` (or another truthy value)
            if(br) { break outer; }
        }
    }

    return this;
}

Plugins.prototype.Init = function(game) {
    this.loop(function(plugin) {
        if(plugin.Init) {
            plugin.Init(game);
        }
    });

    this.initTime = game.Utils.time();

    return this;
}

Plugins.prototype.Load = function(game) {
    this.loop(function(plugin) {
        if(plugin.Load) {
            plugin.Load(game);
        }
    });

    this.loadTime = game.Utils.time();

    return this;
}

Plugins.prototype.Update = function(game) {

    this.loop(function(plugin) {
        if(plugin.Update) {
            plugin.Update(game);
        }
    });

    return this;
}

/*
 * EventEmitter
 *
 * EventEmitter allows for easy event registering and emitting. The API is a copy of the Node.js EventEmitter class.
 */

var EventEmitter = function(obj) {
    if(!obj) obj = this;

    obj.__events = {};
    obj.__allEvents = [];

    obj.addListener = obj.on = function(event, listener) {
        if(!this.__events[event]) this.__events[event] = [];

        if(listener) {
            this.__events[event].push(listener);
        }
        else {
            this.__allEvents.push(event); // event is now the callback
        }

        return this;
    }

    obj.once = function(event, listener) {
        if(!this.__events[event]) this.__events[event] = [];

        if(listener) {
            var func = function() {
                listener.call(null, arguments);
                obj.removeListener(event, func);
            }
            this.__events[event].push(func);
        }
        else {
            var func = function() {
                event.call(null, arguments);
                obj.removeListener(func);
            }
            this.__allEvents.push(func);
        }

        return this;
    }

    obj.emit = function(event, args) {
        if(!args) args = [];
        if(this.__events[event]) {
            var listeners = this.__events[event];
            for(var i = 0, len = listeners.length; i < len; i++) {
                listeners[i].apply(null, args);
            }
        }
        var args = [event].concat(args);
        for(var i = 0, len = this.__allEvents.length; i < len; i++) {
            this.__allEvents[i].apply(null, args);
        }

        return this;
    }

    obj.removeListener = function(event, listener) {
        if(!listener) {
            var listener = event;
            for(event in this.__events) {
                this.removeListener(event, listener);
            }
        }
        else {
            var listeners = this.__events[event];
            if(listeners.indexOf(listener) !== -1) {
                listeners.splice(listeners.indexOf(listener), 1);
            }
            if(this.__allEvents.indexOf(listener) !== -1) {
                this.__allEvents.splice(this.__allEvents.indexOf(listener), 1);
            }
        }

        return this;
    }

    obj.removeAllListeners = function(event) {
        this.__events[event] = [];

        return this;
    }

    obj.listeners = function(event) {
        return this.__events[event] || [];
    }

    return obj;
}

Game.prototype.EventEmitter = EventEmitter;

Game.plugins = [];

/*
 * VARS
 * ====
 *
 * Some variables used  by Game.
 */

    var container = Game.prototype.container = document.createElement("div");
    container.setAttribute("id", "2D-loaders");
    container.setAttribute("style", "width:0;height:0;visibility:hidden;overflow:hidden");
    document.addEventListener("load", function() {
        document.body.appendChild(container);
    });

})();<|endoftext|>


<commit_before>Ext.namespace('Vpc.Abstract.List');

Vpc.Abstract.List.MultiFileUploadPanel = Ext.extend(Ext.Panel,
{
    afterRender: function() {
        Vpc.Abstract.List.MultiFileUploadPanel.superclass.afterRender.call(this);

        var container = this.body.createChild();

        if (!Vps.Utils.Upload.supportsHtml5Upload()) {
            this.swfu = new Vps.Utils.SwfUpload({
                fileSizeLimit: this.list.multiFileUpload.fileSizeLimit,
                allowOnlyImages: this.list.multiFileUpload.allowOnlyImages,
                buttonPlaceholderId: container.id,
                postParams: {
                    maxResolution: this.list.multiFileUpload.maxResolution
                },
                buttonText: trlVps('Upload Files'),
                selectMultiple: true
            });
            this.swfu.on('fileQueued', function(file) {
                if (!this.files) this.files = [];
                this.files.push(file.id);

                if (this.running) {
                    return;
                }

                this.uploadedIds = [];
                this.running = true;
                this.progress = Ext.MessageBox.show({
                    title : trlVps('Upload'),
                    msg : trlVps('Uploading files'),
                    buttons: false,
                    progress:true,
                    closable:false,
                    minWidth: 250,
                    buttons: Ext.MessageBox.CANCEL,
                    scope: this,
                    fn: function(button) {
                        for(var i=0;i<this.files.length;i++) {
                            if (this.swfu.getFile(i)) this.swfu.cancelUpload(this.swfu.getFile(i).id);
                        }
                        this.files = [];
                        this.running = false;
                    }
                });
                this.swfu.startUpload(file.id);
            }, this);
            this.swfu.on('uploadProgress', function(file, done, total) {
                var total = 0;
                var sumDone = 0;
                for(var i=0;i<this.files.length;i++) {
                    total += this.swfu.getFile(i).size;
                    if (this.swfu.getFile(i).id == file.id) {
                        sumDone += done;
                    } else if (this.swfu.getFile(i).filestatus != SWFUpload.FILE_STATUS.QUEUED) {
                        sumDone += this.swfu.getFile(i).size;
                    }
                }
                this.progress.updateProgress(sumDone/total);
            }, this);
            this.swfu.on('uploadSuccess', function(file, r) {
                this.uploadedIds.push(r.value.uploadId);

                for(var i=0;i<this.files.length;i++) {
                    if (this.swfu.getFile(i).filestatus == SWFUpload.FILE_STATUS.QUEUED) {
                        //neeext
                        this.swfu.startUpload(this.swfu.getFile(i).id);
                        return;
                    }
                }
                this.running = false;
                this.files = [];
                this.progress.hide();

                var params = Ext.apply(this.list.getBaseParams(), { uploadIds: this.uploadedIds.join(',')});
                Ext.Ajax.request({
                    url: this.list.controllerUrl+'/json-multi-upload',
                    params: params,
                    success: function() {
                        this.list.grid.reload();
                    },
                    scope: this
                })
            }, this);
            this.swfu.on('uploadError', function(file, errorCode, errorMessage) {
                this.progress.hide();
            }, this);
        } else {
            container.setStyle('position', 'relative');
            this.uploadButton = new Ext.Button({
                text: trlVps('Upload Files'),
                cls: 'x-btn-text-icon',
                icon: '/assets/silkicons/add.png',
                renderTo: container
            });

            var fileInputContainer = container.createChild({
                style: 'width: 120px; height: 20px; top: 0; position: absolute; overflow: hidden;'
            });

            var fileInput = fileInputContainer.createChild({
                tag: 'input',
                type: 'file',
                multiple: 'multiple',
                style: 'opacity: 0; cursor: pointer; '
            });
            fileInput.on('change', function(ev, dom) {
                if (dom.files) {
                    this.html5UploadFiles(dom.files);
                    dom.value = ''; //leeren, damit gleiche datei nochmal gewählt werden kann
                }
            }, this);

            this.list.westPanel.el.on('dragenter', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
            }, this);
            this.list.westPanel.el.on('dragover', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
            }, this);
            this.list.westPanel.el.on('drop', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
                if (e.browserEvent.dataTransfer) {
                    this.html5UploadFiles(e.browserEvent.dataTransfer.files);
                }
            }, this);
        }
    },
    html5UploadFiles: function(files)
    {
        if (!files.length) return;

        this.progress = Ext.MessageBox.show({
            title : trlVps('Upload'),
            msg : trlVps('Uploading files'),
            buttons: false,
            progress:true,
            closable:false,
            minWidth: 250,
            buttons: Ext.MessageBox.CANCEL,
            scope: this,
            fn: function(button) {
                this.fileQueue = [];
                this.currentXhr.abort();
            }
        });

        this.processedFiles = [];
        this.fileQueue = [];
        this.uploadedIds = [];
        for(var i=0;i<files.length;++i) {
            this.fileQueue.push(files[i]);
        }
        this.html5UploadFile();
    },

    updateProgress: function(e)
    {
        var total = 0;
        if (e && e.total) total += e.total;
        var loaded = 0;
        if (e && e.loaded) loaded += e.loaded;
        this.processedFiles.forEach(function(f) {
            total += f.size;
            loaded += f.size;
        }, this);
        this.fileQueue.forEach(function(f) {
            total += f.size;
        }, this);
        this.progress.updateProgress(loaded / total);
    },

    html5UploadFile: function()
    {
        var file = this.fileQueue.pop();
        this.currentXhr = Vps.Utils.Upload.uploadFile({
            maxResolution: this.maxResolution,
            file: file,
            success: function(r, options) {
                this.processedFiles.push(options.file);
                this.uploadedIds.push(r.value.uploadId);
                if (this.fileQueue.length) {
                    this.updateProgress();
                    this.html5UploadFile(); //neext
                } else {
                    var params = Ext.apply(this.list.getBaseParams(), { uploadIds: this.uploadedIds.join(',')});
                    Ext.Ajax.request({
                        url: this.list.controllerUrl+'/json-multi-upload',
                        params: params,
                        success: function() {
                            this.progress.hide();
                            this.list.grid.reload();
                        },
                        scope: this
                    });
                }
            },
            failure: function() {
                this.progress.hide();
            },
            progress: function(e) {
                this.updateProgress(e);
            },
            scope: this
        });
    },
    onDestroy: function() {
        this.swfu.destroy();
    }
});
Vpc.Abstract.List.Panel = Ext.extend(Vps.Binding.ProxyPanel,
{
    border: false,
    initComponent: function()
    {
        this.childPanel = Ext.ComponentMgr.create(Ext.applyIf(this.childConfig, {
            region: 'center'
        }));

        this.grid = new Vps.Auto.GridPanel({
            controllerUrl: this.controllerUrl,
            split: true,
            region: 'center',
            baseParams: this.baseParams, //Kompatibilität zu ComponentPanel
            autoLoad: this.autoLoad,
            bindings: [{
                item        : this.childPanel,
                componentIdSuffix: '-{0}'
            }],
            onAdd: this.onAdd
        });
        this.proxyItem = this.grid;

        this.grid.on('datachange', function() {
            this.childPanel.reload();
        }, this);

        var westItems = [this.grid];

        if (this.multiFileUpload) {
            this.multiFileUploadPanel = new Vpc.Abstract.List.MultiFileUploadPanel({
                border: false,
                region: 'south',
                height: 50,
                bodyStyle: 'padding-top: 15px; padding-left:80px;',
                list: this
            });
            westItems.push(this.multiFileUploadPanel);
        }

        this.westPanel = new Ext.Panel({
            layout: 'border',
            region: 'west',
            width: 300,
            border: false,
            items: westItems
        });

        this.layout = 'border';
        this.items = [this.westPanel, this.childPanel];
        Vpc.Abstract.List.Panel.superclass.initComponent.call(this);
    },

    load: function()
    {
        this.grid.load();
        this.grid.selectId(false);

        this.childPanel.setBaseParams({});
        var f = this.childPanel.getForm();
        if (f) {
            f.clearValues();
            f.clearInvalid();
        }
        this.childPanel.disable();
    },

    onAdd : function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-insert',
            params: this.getBaseParams(),
            success: function(response, options, r) {
                this.getSelectionModel().clearSelections();
                this.reload({
                    callback: function(o, r, s) {
                        this.getSelectionModel().selectLastRow();
                    },
                    scope: this
                });
            },
            scope: this
        });
    }
});
Ext.reg('vpc.list', Vpc.Abstract.List.Panel);
<commit_msg>Vpc_List: title fuer child ausblenden, der macht da keinen sinn<commit_after>Ext.namespace('Vpc.Abstract.List');

Vpc.Abstract.List.MultiFileUploadPanel = Ext.extend(Ext.Panel,
{
    afterRender: function() {
        Vpc.Abstract.List.MultiFileUploadPanel.superclass.afterRender.call(this);

        var container = this.body.createChild();

        if (!Vps.Utils.Upload.supportsHtml5Upload()) {
            this.swfu = new Vps.Utils.SwfUpload({
                fileSizeLimit: this.list.multiFileUpload.fileSizeLimit,
                allowOnlyImages: this.list.multiFileUpload.allowOnlyImages,
                buttonPlaceholderId: container.id,
                postParams: {
                    maxResolution: this.list.multiFileUpload.maxResolution
                },
                buttonText: trlVps('Upload Files'),
                selectMultiple: true
            });
            this.swfu.on('fileQueued', function(file) {
                if (!this.files) this.files = [];
                this.files.push(file.id);

                if (this.running) {
                    return;
                }

                this.uploadedIds = [];
                this.running = true;
                this.progress = Ext.MessageBox.show({
                    title : trlVps('Upload'),
                    msg : trlVps('Uploading files'),
                    buttons: false,
                    progress:true,
                    closable:false,
                    minWidth: 250,
                    buttons: Ext.MessageBox.CANCEL,
                    scope: this,
                    fn: function(button) {
                        for(var i=0;i<this.files.length;i++) {
                            if (this.swfu.getFile(i)) this.swfu.cancelUpload(this.swfu.getFile(i).id);
                        }
                        this.files = [];
                        this.running = false;
                    }
                });
                this.swfu.startUpload(file.id);
            }, this);
            this.swfu.on('uploadProgress', function(file, done, total) {
                var total = 0;
                var sumDone = 0;
                for(var i=0;i<this.files.length;i++) {
                    total += this.swfu.getFile(i).size;
                    if (this.swfu.getFile(i).id == file.id) {
                        sumDone += done;
                    } else if (this.swfu.getFile(i).filestatus != SWFUpload.FILE_STATUS.QUEUED) {
                        sumDone += this.swfu.getFile(i).size;
                    }
                }
                this.progress.updateProgress(sumDone/total);
            }, this);
            this.swfu.on('uploadSuccess', function(file, r) {
                this.uploadedIds.push(r.value.uploadId);

                for(var i=0;i<this.files.length;i++) {
                    if (this.swfu.getFile(i).filestatus == SWFUpload.FILE_STATUS.QUEUED) {
                        //neeext
                        this.swfu.startUpload(this.swfu.getFile(i).id);
                        return;
                    }
                }
                this.running = false;
                this.files = [];
                this.progress.hide();

                var params = Ext.apply(this.list.getBaseParams(), { uploadIds: this.uploadedIds.join(',')});
                Ext.Ajax.request({
                    url: this.list.controllerUrl+'/json-multi-upload',
                    params: params,
                    success: function() {
                        this.list.grid.reload();
                    },
                    scope: this
                })
            }, this);
            this.swfu.on('uploadError', function(file, errorCode, errorMessage) {
                this.progress.hide();
            }, this);
        } else {
            container.setStyle('position', 'relative');
            this.uploadButton = new Ext.Button({
                text: trlVps('Upload Files'),
                cls: 'x-btn-text-icon',
                icon: '/assets/silkicons/add.png',
                renderTo: container
            });

            var fileInputContainer = container.createChild({
                style: 'width: 120px; height: 20px; top: 0; position: absolute; overflow: hidden;'
            });

            var fileInput = fileInputContainer.createChild({
                tag: 'input',
                type: 'file',
                multiple: 'multiple',
                style: 'opacity: 0; cursor: pointer; '
            });
            fileInput.on('change', function(ev, dom) {
                if (dom.files) {
                    this.html5UploadFiles(dom.files);
                    dom.value = ''; //leeren, damit gleiche datei nochmal gewählt werden kann
                }
            }, this);

            this.list.westPanel.el.on('dragenter', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
            }, this);
            this.list.westPanel.el.on('dragover', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
            }, this);
            this.list.westPanel.el.on('drop', function(e) {
                e.browserEvent.stopPropagation();
                e.browserEvent.preventDefault();
                if (e.browserEvent.dataTransfer) {
                    this.html5UploadFiles(e.browserEvent.dataTransfer.files);
                }
            }, this);
        }
    },
    html5UploadFiles: function(files)
    {
        if (!files.length) return;

        this.progress = Ext.MessageBox.show({
            title : trlVps('Upload'),
            msg : trlVps('Uploading files'),
            buttons: false,
            progress:true,
            closable:false,
            minWidth: 250,
            buttons: Ext.MessageBox.CANCEL,
            scope: this,
            fn: function(button) {
                this.fileQueue = [];
                this.currentXhr.abort();
            }
        });

        this.processedFiles = [];
        this.fileQueue = [];
        this.uploadedIds = [];
        for(var i=0;i<files.length;++i) {
            this.fileQueue.push(files[i]);
        }
        this.html5UploadFile();
    },

    updateProgress: function(e)
    {
        var total = 0;
        if (e && e.total) total += e.total;
        var loaded = 0;
        if (e && e.loaded) loaded += e.loaded;
        this.processedFiles.forEach(function(f) {
            total += f.size;
            loaded += f.size;
        }, this);
        this.fileQueue.forEach(function(f) {
            total += f.size;
        }, this);
        this.progress.updateProgress(loaded / total);
    },

    html5UploadFile: function()
    {
        var file = this.fileQueue.pop();
        this.currentXhr = Vps.Utils.Upload.uploadFile({
            maxResolution: this.maxResolution,
            file: file,
            success: function(r, options) {
                this.processedFiles.push(options.file);
                this.uploadedIds.push(r.value.uploadId);
                if (this.fileQueue.length) {
                    this.updateProgress();
                    this.html5UploadFile(); //neext
                } else {
                    var params = Ext.apply(this.list.getBaseParams(), { uploadIds: this.uploadedIds.join(',')});
                    Ext.Ajax.request({
                        url: this.list.controllerUrl+'/json-multi-upload',
                        params: params,
                        success: function() {
                            this.progress.hide();
                            this.list.grid.reload();
                        },
                        scope: this
                    });
                }
            },
            failure: function() {
                this.progress.hide();
            },
            progress: function(e) {
                this.updateProgress(e);
            },
            scope: this
        });
    },
    onDestroy: function() {
        this.swfu.destroy();
    }
});
Vpc.Abstract.List.Panel = Ext.extend(Vps.Binding.ProxyPanel,
{
    border: false,
    initComponent: function()
    {
        if (this.childConfig.title) delete this.childConfig.title;
        this.childPanel = Ext.ComponentMgr.create(Ext.applyIf(this.childConfig, {
            region: 'center'
        }));

        this.grid = new Vps.Auto.GridPanel({
            controllerUrl: this.controllerUrl,
            split: true,
            region: 'center',
            baseParams: this.baseParams, //Kompatibilität zu ComponentPanel
            autoLoad: this.autoLoad,
            bindings: [{
                item        : this.childPanel,
                componentIdSuffix: '-{0}'
            }],
            onAdd: this.onAdd
        });
        this.proxyItem = this.grid;

        this.grid.on('datachange', function() {
            this.childPanel.reload();
        }, this);

        var westItems = [this.grid];

        if (this.multiFileUpload) {
            this.multiFileUploadPanel = new Vpc.Abstract.List.MultiFileUploadPanel({
                border: false,
                region: 'south',
                height: 50,
                bodyStyle: 'padding-top: 15px; padding-left:80px;',
                list: this
            });
            westItems.push(this.multiFileUploadPanel);
        }

        this.westPanel = new Ext.Panel({
            layout: 'border',
            region: 'west',
            width: 300,
            border: false,
            items: westItems
        });

        this.layout = 'border';
        this.items = [this.westPanel, this.childPanel];
        Vpc.Abstract.List.Panel.superclass.initComponent.call(this);
    },

    load: function()
    {
        this.grid.load();
        this.grid.selectId(false);

        this.childPanel.setBaseParams({});
        var f = this.childPanel.getForm();
        if (f) {
            f.clearValues();
            f.clearInvalid();
        }
        this.childPanel.disable();
    },

    onAdd : function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-insert',
            params: this.getBaseParams(),
            success: function(response, options, r) {
                this.getSelectionModel().clearSelections();
                this.reload({
                    callback: function(o, r, s) {
                        this.getSelectionModel().selectLastRow();
                    },
                    scope: this
                });
            },
            scope: this
        });
    }
});
Ext.reg('vpc.list', Vpc.Abstract.List.Panel);
<|endoftext|>


<commit_before>// Start enchant.js
enchant();

var browserWidth = window.innerWidth || document.body.clientWidth;
var browserHeight = window.innerHeight || document.body.clientHeight + 100;
window.onload = function() {

    // Starting point
    //var game = new Game(320, 440);
	//var game = new Game(440, 320);
	var game = new Game(browserWidth, browserHeight);
    game.preload(
                 'res/unicornSheetV1.png',
                 'res/drive.png',
				 'res/unicornGameOver.png',
                 'res/Hit.mp3',
                 'res/bgm.mp3',
				 'res/deadUnicornV001.jpg');
    game.fps = 30;
    game.scale = 1;
    game.onload = function() {
        // Once Game finish loading
        console.log("Hi, Boxer!");
        var scene = new SceneGame();
        game.pushScene(scene);
    }
    window.scrollTo(0,0);
    game.start();
};

/**
 * SceneGame
 */
var SceneGame = Class.create(Scene, {
    /**
     * The main gameplay scene.
     */
    initialize: function() {
        var game, label, bg, unicorn, driveGroup;

        // Call superclass constructor
        Scene.apply(this);

        // Access to the game singleton instance
        game = Game.instance;

        label = new Label('SCORE:
0');
        label.x = game.width/2-130;
        label.y = 32;
        label.color = 'black';
        label.font = '16px strong';
        label.textAlign = 'center';
        label._style.textShadow ="-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black";
        this.scoreLabel = label;

        bg = new Sprite(browserWidth, browserHeight);

        unicorn = new Unicorn();
        unicorn.y = game.height/2 - unicorn.height/2;
        unicorn.x = 10;
        this.unicorn = unicorn;

        driveGroup = new Group();
        this.driveGroup = driveGroup;

        this.addChild(bg);
        this.addChild(driveGroup);
        this.addChild(unicorn);
        this.addChild(label);

        this.addEventListener(Event.TOUCH_START,this.handleTouchControl);
        this.addEventListener(Event.ENTER_FRAME,this.update);

        // Instance variables
        this.generatedriveTimer = 0;
        this.scoreTimer = 0;
        this.score = 0;

        this.bgm = game.assets['res/bgm.mp3']; // Add this line

        // Start BGM
        this.bgm.play();
    },

    handleTouchControl: function (evt) {
        var laneHeight, lane;
        laneHeight = 600/3;
        lane = Math.floor(evt.y/laneHeight);
        lane = Math.max(Math.min(2,lane),0);
        this.unicorn.switchToLaneNumber(lane);
    },

    update: function(evt) {
        // Score increase as time pass
        this.scoreTimer += evt.elapsed * 0.001;
        if(this.scoreTimer >= 0.5)
        {
            this.setScore(this.score + 1);
            this.scoreTimer -= 0.5;
        }

        // Check if it's time to create a new set of obstacles
        this.generatedriveTimer += evt.elapsed * 0.001;
        if(this.generatedriveTimer >= 0.5)
        {
            var drive;
            this.generatedriveTimer -= 0.5;
            drive = new Drive(Math.floor(Math.random()*3));
            this.driveGroup.addChild(drive);
        }

        // Check collision
        for (var i = this.driveGroup.childNodes.length - 1; i >= 0; i--) {
            var drive;
            drive = this.driveGroup.childNodes[i];
            if(drive.intersect(this.unicorn)){
                var game;
                game = Game.instance;
                game.assets['res/Hit.mp3'].play();
                this.driveGroup.removeChild(drive);
                this.bgm.stop();
                game.replaceScene(new SceneGameOver(this.score));
                break;
            }
        }

        // Loop BGM
        if( this.bgm.currentTime >= this.bgm.duration ){
            this.bgm.play();
        }
    },

    setScore: function (value) {
        this.score = value;
        this.scoreLabel.text = 'SCORE
' + this.score;
    }
});

/**
 * unicorn
 */
 var Unicorn = Class.create(Sprite, {
    /**
     * The player character.
     */
    initialize: function() {
        // Call superclass constructor
        Sprite.apply(this,[100, 60]);
        this.image = Game.instance.assets['res/unicornSheetV1.png'];
        this.animationDuration = 0;
        this.addEventListener(Event.ENTER_FRAME, this.updateAnimation);
    },

    updateAnimation: function (evt) {
        this.animationDuration += evt.elapsed * 0.001;
        if(this.animationDuration >= 0.25)
        {
            this.frame = (this.frame + 1) % 2;
            this.animationDuration -= 0.25;
        }
    },

    switchToLaneNumber: function(lane){
        var targetY = 300 - this.height/2 + (lane-1)*170;
        this.y = targetY;
    }
});

var UnicornGameOver = Class.create (Sprite, {
	initialize: function() {
		Sprite.apply(this,[browserWidth,browserHeight]);
		this.image = Game.instance.assets['res/deadUnicornV001.jpg'];
	}
});

var Drive = Class.create(Sprite, {
    /**
     * The obstacle that the unicorn must avoid
     */
    initialize: function(lane) {
        // Call superclass constructor
        Sprite.apply(this,[48, 49]);
        this.image  = Game.instance.assets['res/drive.png'];
        this.rotationSpeed = 0;
        this.setLane(lane);
        this.addEventListener(Event.ENTER_FRAME, this.update);
    },

    setLane: function(lane) {
        var game, distance;
        game = Game.instance;
        distance = 170;

        this.rotationSpeed = Math.random() * 100 - 50;

        this.y = game.height/2 - this.height/2 + (lane - 1) * distance;
        this.x = game.width;
        this.rotation = Math.floor( Math.random() * 360 );
    },

    update: function(evt) {
        var ySpeed, game;

        game = Game.instance;
        ySpeed = 300;

        this.x -= ySpeed * evt.elapsed * 0.001;
        this.rotation += this.rotationSpeed * evt.elapsed * 0.001;
        if(this.x < 0)
        {
            this.parentNode.removeChild(this);
        }
    }
});

/**
 * SceneGameOver
 */
var SceneGameOver = Class.create(Scene, {
    initialize: function(score) {
        var gameOverLabel, scoreLabel, unicornGameOver, game;
		game = Game.instance;
        Scene.apply(this);
        this.backgroundColor = 'black';
		this.image = Game.instance.assets['res/deadUnicornV001.jpg'];

        gameOverLabel = new Label("GAME OVER

Tap to Restart");
        gameOverLabel.x = (game.width/2)-150;
        gameOverLabel.y = (game.height/2)-100;
        gameOverLabel.color = 'white';
        gameOverLabel.font = '32px strong';
        gameOverLabel.textAlign = 'center';

        scoreLabel = new Label('SCORE
' + score);
        scoreLabel.x = (game.width/2)-150;
        scoreLabel.y = 50;
        scoreLabel.color = 'white';
        scoreLabel.font = '16px strong';
        scoreLabel.textAlign = 'center';

		unicornGameOver = new UnicornGameOver();

		this.addChild(unicornGameOver);
        this.addChild(gameOverLabel);
        this.addChild(scoreLabel);

        this.addEventListener(Event.TOUCH_START, this.touchToRestart);

    },

    touchToRestart: function(evt) {
        var game = Game.instance;
        game.replaceScene(new SceneGame());
    }
});<commit_msg>Revert ee5ca63..88257c4<commit_after>// Start enchant.js
enchant();

var browserWidth = window.innerWidth || document.body.clientWidth;
var browserHeight = window.innerHeight || document.body.clientHeight;
window.onload = function() {

    // Starting point
    //var game = new Game(320, 440);
	//var game = new Game(440, 320);
	var game = new Game(browserWidth, browserHeight);
    game.preload(
                 'res/unicornSheetV1.png',
                 'res/drive.png',
				 'res/unicornGameOver.png',
                 'res/Hit.mp3',
                 'res/bgm.mp3',
				 'res/deadUnicornV001.jpg');
    game.fps = 30;
    game.scale = 1;
    game.onload = function() {
        // Once Game finish loading
        console.log("Hi, Boxer!");
        var scene = new SceneGame();
        game.pushScene(scene);
    }
    window.scrollTo(0,0);
    game.start();
};

/**
 * SceneGame
 */
var SceneGame = Class.create(Scene, {
    /**
     * The main gameplay scene.
     */
    initialize: function() {
        var game, label, bg, unicorn, driveGroup;

        // Call superclass constructor
        Scene.apply(this);

        // Access to the game singleton instance
        game = Game.instance;

        label = new Label('SCORE:
0');
        label.x = game.width/2-130;
        label.y = 32;
        label.color = 'black';
        label.font = '16px strong';
        label.textAlign = 'center';
        label._style.textShadow ="-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black";
        this.scoreLabel = label;

        bg = new Sprite(browserWidth, browserHeight);

        unicorn = new Unicorn();
        unicorn.y = game.height/2 - unicorn.height/2;
        unicorn.x = 10;
        this.unicorn = unicorn;

        driveGroup = new Group();
        this.driveGroup = driveGroup;

        this.addChild(bg);
        this.addChild(driveGroup);
        this.addChild(unicorn);
        this.addChild(label);

        this.addEventListener(Event.TOUCH_START,this.handleTouchControl);
        this.addEventListener(Event.ENTER_FRAME,this.update);

        // Instance variables
        this.generatedriveTimer = 0;
        this.scoreTimer = 0;
        this.score = 0;

        this.bgm = game.assets['res/bgm.mp3']; // Add this line

        // Start BGM
        this.bgm.play();
    },

    handleTouchControl: function (evt) {
        var laneHeight, lane;
        laneHeight = 600/3;
        lane = Math.floor(evt.y/laneHeight);
        lane = Math.max(Math.min(2,lane),0);
        this.unicorn.switchToLaneNumber(lane);
    },

    update: function(evt) {
        // Score increase as time pass
        this.scoreTimer += evt.elapsed * 0.001;
        if(this.scoreTimer >= 0.5)
        {
            this.setScore(this.score + 1);
            this.scoreTimer -= 0.5;
        }

        // Check if it's time to create a new set of obstacles
        this.generatedriveTimer += evt.elapsed * 0.001;
        if(this.generatedriveTimer >= 0.5)
        {
            var drive;
            this.generatedriveTimer -= 0.5;
            drive = new Drive(Math.floor(Math.random()*3));
            this.driveGroup.addChild(drive);
        }

        // Check collision
        for (var i = this.driveGroup.childNodes.length - 1; i >= 0; i--) {
            var drive;
            drive = this.driveGroup.childNodes[i];
            if(drive.intersect(this.unicorn)){
                var game;
                game = Game.instance;
                game.assets['res/Hit.mp3'].play();
                this.driveGroup.removeChild(drive);
                this.bgm.stop();
                game.replaceScene(new SceneGameOver(this.score));
                break;
            }
        }

        // Loop BGM
        if( this.bgm.currentTime >= this.bgm.duration ){
            this.bgm.play();
        }
    },

    setScore: function (value) {
        this.score = value;
        this.scoreLabel.text = 'SCORE
' + this.score;
    }
});

/**
 * unicorn
 */
 var Unicorn = Class.create(Sprite, {
    /**
     * The player character.
     */
    initialize: function() {
        // Call superclass constructor
        Sprite.apply(this,[100, 60]);
        this.image = Game.instance.assets['res/unicornSheetV1.png'];
        this.animationDuration = 0;
        this.addEventListener(Event.ENTER_FRAME, this.updateAnimation);
    },

    updateAnimation: function (evt) {
        this.animationDuration += evt.elapsed * 0.001;
        if(this.animationDuration >= 0.25)
        {
            this.frame = (this.frame + 1) % 2;
            this.animationDuration -= 0.25;
        }
    },

    switchToLaneNumber: function(lane){
        var targetY = 300 - this.height/2 + (lane-1)*170;
        this.y = targetY;
    }
});

var UnicornGameOver = Class.create (Sprite, {
	initialize: function() {
		Sprite.apply(this,[browserWidth,browserHeight]);
		this.image = Game.instance.assets['res/deadUnicornV001.jpg'];
	}
});

var Drive = Class.create(Sprite, {
    /**
     * The obstacle that the unicorn must avoid
     */
    initialize: function(lane) {
        // Call superclass constructor
        Sprite.apply(this,[48, 49]);
        this.image  = Game.instance.assets['res/drive.png'];
        this.rotationSpeed = 0;
        this.setLane(lane);
        this.addEventListener(Event.ENTER_FRAME, this.update);
    },

    setLane: function(lane) {
        var game, distance;
        game = Game.instance;
        distance = 170;

        this.rotationSpeed = Math.random() * 100 - 50;

        this.y = game.height/2 - this.height/2 + (lane - 1) * distance;
        this.x = game.width;
        this.rotation = Math.floor( Math.random() * 360 );
    },

    update: function(evt) {
        var ySpeed, game;

        game = Game.instance;
        ySpeed = 300;

        this.x -= ySpeed * evt.elapsed * 0.001;
        this.rotation += this.rotationSpeed * evt.elapsed * 0.001;
        if(this.x < 0)
        {
            this.parentNode.removeChild(this);
        }
    }
});

/**
 * SceneGameOver
 */
var SceneGameOver = Class.create(Scene, {
    initialize: function(score) {
        var gameOverLabel, scoreLabel, unicornGameOver, game;
		game = Game.instance;
        Scene.apply(this);
        this.backgroundColor = 'black';
		this.image = Game.instance.assets['res/deadUnicornV001.jpg'];

        gameOverLabel = new Label("GAME OVER

Tap to Restart");
        gameOverLabel.x = (game.width/2)-150;
        gameOverLabel.y = (game.height/2)-100;
        gameOverLabel.color = 'white';
        gameOverLabel.font = '32px strong';
        gameOverLabel.textAlign = 'center';

        scoreLabel = new Label('SCORE
' + score);
        scoreLabel.x = (game.width/2)-150;
        scoreLabel.y = 50;
        scoreLabel.color = 'white';
        scoreLabel.font = '16px strong';
        scoreLabel.textAlign = 'center';

		unicornGameOver = new UnicornGameOver();

		this.addChild(unicornGameOver);
        this.addChild(gameOverLabel);
        this.addChild(scoreLabel);

        this.addEventListener(Event.TOUCH_START, this.touchToRestart);

    },

    touchToRestart: function(evt) {
        var game = Game.instance;
        game.replaceScene(new SceneGame());
    }
});<|endoftext|>