<commit_before>var buttons = null;
var button = [];
var main = null;
var conversations = [];
var contacts = null;
var phone = null;
var last = null;
var state = 'idle';
var statusline = null;

var contact = {};

var number = null;

var token = null;
var connection = null;
var incoming = null;

var last = new Date().toISOString();

var xhr = function(method, resource, data, callback) {
	var req = new XMLHttpRequest();

	req.responseType = 'json';

	req.addEventListener('load', function(ev) {
		callback === undefined || callback(req.response);
	});

	req.open(method, resource);
	if (data === undefined) {
		req.send();
	}
	else {
		req.setRequestHeader('Content-Type', 'application/json');
		req.send(JSON.stringify(data));
	}
};

var load = function() {
	// get elements
	buttons = document.getElementById('buttons');
	button = document.getElementById('buttons').children;
	main = document.getElementById('main');
	conversations = [];
	contacts = document.getElementById('contacts');
	phone = document.getElementById('phone');
	statusline = document.getElementById('status');

	contact = {};

	// load contacts
	xhr('get', '/contacts/', undefined, function(response) {
		contact = response;

		Object.keys(contact).forEach(function(key) {
			var li = document.createElement('li');

			var span_name = document.createElement('span');
			var span_number = document.createElement('span');
			var button_call = document.createElement('button');
			var button_message = document.createElement('button');

			span_name.innerText = contact[key];
			span_number.innerText = key;

			button_call.innerText = 'Call';
			button_message.innerText = 'Message';

			button_call.addEventListener('click', function(ev) {
				window.call(key);
			});
			button_message.addEventListener('click', function(ev) {
				window.open(key);
			});

			li.appendChild(span_name);
			li.appendChild(span_number);
			li.appendChild(button_call);
			li.appendChild(button_message);

			contacts.appendChild(li);
		});
	});

	// setup callbacks
	xhr('get', '/browser', undefined, function(data) {
		// get number
		number = data.number;

		// get token
		token = data.token;

		// setup Twilio.Device
		Twilio.Device.setup(token);

		Twilio.Device.connect(function (conn) {
			state = 'connected';
			statusline.innerText = 'Connected.';
		});

		Twilio.Device.disconnect(function (conn) {
			state = 'idle';
			statusline.innerText = 'Dial a Number';
		});

		Twilio.Device.incoming(function (conn) {
			state = 'incoming';

			incoming = conn;

			// get from name
			from = conn.parameters.From;

			if (from in contact)
				from = contact[from];

			statusline.innerText = 'Incoming Call From ' + from;

			// open phone
			select('phone');
		});

		Twilio.Device.offline(function(device) {
			// get another token
			xhr('get', '/browser', undefined, function(data) {
				// get token
				token = data.token;

				// setup Twilio.Device
				Twilio.Device.setup(token);
			});
		});

		// setup message callbacks
		var messageUpdate = function() {
			var current = last;
			var next = new Date().toISOString();

			xhr('get', '/msgs/?date_sent_after=' + current + '&to=' + number, undefined, function(data) {
				data.forEach(function(msg) {
					open(msg.from, current);
				});
			});

			xhr('get', '/msgs/?date_sent_after=' + current + '&from=' + number, undefined, function(data) {
				data.forEach(function(msg) {
					open(msg.to, current);
				});
			});

			last = next;

			setTimeout(messageUpdate, 1000);
		};

		// initiate message updates
		messageUpdate();

		// mark online
		xhr('post', '/browser', {'online': true});
	});

	// select nothing
	select(null);

	// show body
	document.body.style.display = 'flex';
};

var unload = function() {
	// mark offline
	xhr('post', '/browser', {'online': false});
};

var open = function(number, date) {
	if (document.getElementById(number) === null) {
		// create new chat block
		var chat = document.createElement('div');
		chat.id = number;
		chat.classList.add('chat');

		var container = document.createElement('div');

		var input = document.createElement('input');
		input.type = 'text';
		input.placeholder = 'Enter Message Here...';

		chat.appendChild(container);
		chat.appendChild(input);

		main.appendChild(chat);
		conversations.push(chat);

		// create button
		var button = document.createElement('button');
		button.id = 'button_' + number;
		button.addEventListener('click', function(ev) { window.select(number) });

		buttons.insertBefore(button, buttons.firstChild);
	}

	base = '/msgs/?';

	if (date !== undefined)
		base += 'date_sent_after=' + date + '&';

	// load chat
	xhr('get', base + 'to=' + number, function(data) {
		xhr('get', base + 'from=' + number, function(dataInner) {
			// get all messages
			var messages = data.concat(dataInner);

			// sort by date
			messages.sort(function(left, right) {
				return new Date(right.date) - new Date(left.date);
			});

			// generate elements
			messages.forEach(function(message) {
				// create chat bubble
				var div = document.createElement('div');

				// set class based on whether this was sent or receieved
				if (message.from === number)
					div.classList.add('me');
				else
					div.classList.add('you');

				// get message time
				var date = new Date(message.date);

				// format time
				var time = document.createElement('time');
				time.innerText = '';
				time.innerText += date.getFullYear();
				time.innerText += ('0' + (date.Month() + 1)).slice(-2);
				time.innerText += ('0' + date.getDate()).slice(-2);
				time.innerText += ' ';
				time.innerText += ('0' + date.getHours()).slice(-2);
				time.innerText += ':';
				time.innerText += ('0' + date.getSeconds()).slice(-2);

				// add body
				var p = document.createElement('p');
				p.innerText = message.body;

				// join time and body into message
				div.appendChild(time);
				div.appendChild(p);

				// add message to chat window
				document.getElementById(number).children[0].appendChild(div);
			});

			// bring chat forward
			select(number);
		});
	});
};

var close = function(number) {
	if (conversations.indexOf(number) === -1)
		return;

	// remove chat block
	main.removeChild(conversations[number]);

	// bring last thing forward
	select(last);
};

var click = function(key) {
	if (state === 'connecting' || state === 'connected') {
		if (key === 'hangup') {
			hangup();
		}
		else if (key === 'dial') {
			// do nothing
		}
		else {
			connection.sendDigits(key);
		}
	}
	else if (state === 'idle') {
		if (key === 'hangup') {
			// do nothing
		}
		else if (key === 'dial') {
			// do nothing
		}
		else {
			statusline.innerText = key;
		}

		state = 'dialing';
	}
	else if (state === 'dialing') {
		if (key === 'dial') {
			call(statusline.innerText);
		}
		else if (key === 'hangup') {
			statusline.innerText = 'Dial a Number';

			state = 'idle';
		}
		else {
			statusline.innerText += key;
		}
	}
	else if (state === 'incoming') {
		if (key === 'dial') {
			incoming.accept();

			connection = incoming;
		}
		else if (key === 'hangup') {
			incoming.reject();
		}

		state = 'connected';
		status.innerText = 'Connected.';
	}
};

var call = function(number) {
	// update state
	state = 'connecting';

	// create connection
	connection = Twilio.Device.connect({'To': number});

	// call number
	select('phone');
};

var hangup = function() {
	// close phone
	select(last);

	// disconnect line
	Twilio.Device.disconnectAll();
};

var select = function(id) {
	if (id === 'toggle') {
		if (phone.style.display === 'none')
			// behave as though phone were selected
			id = 'phone';
		else
			// behave as though last were selected
			id = last;
	}

	if (id === 'phone') {
		// simply display phone
		phone.style.display = '';
	}
	else {
		// close all conversations
		conversations.forEach(function(element) {
			element.style.display = 'none';
		});

		// close phone and contacts
		contacts.style.display = 'none';
		phone.style.display = 'none';

		// display requested section
		if (id !== null)
			document.getElementById(id).style.display = '';
	}

	// disable all buttons
	for (var idx = 0; idx < button.length; idx++)
		button[idx].classList.remove('active');

	// mark respective button as active
	if (id !== null)
		document.getElementById('button_' + id).classList.add('active');

	if (id !== 'phone')
		last = id;
};

window.addEventListener('load', load);
window.addEventListener('unload', unload);
<commit_msg>fix variable collision<commit_after>var buttons = null;
var button = [];
var main = null;
var conversations = [];
var contacts = null;
var phone = null;
var last = null;
var state = 'idle';
var statusline = null;

var contact = {};

var number = null;

var token = null;
var connection = null;
var incoming = null;

var messageTime = new Date().toISOString();

var xhr = function(method, resource, data, callback) {
	var req = new XMLHttpRequest();

	req.responseType = 'json';

	req.addEventListener('load', function(ev) {
		callback === undefined || callback(req.response);
	});

	req.open(method, resource);
	if (data === undefined) {
		req.send();
	}
	else {
		req.setRequestHeader('Content-Type', 'application/json');
		req.send(JSON.stringify(data));
	}
};

var load = function() {
	// get elements
	buttons = document.getElementById('buttons');
	button = document.getElementById('buttons').children;
	main = document.getElementById('main');
	conversations = [];
	contacts = document.getElementById('contacts');
	phone = document.getElementById('phone');
	statusline = document.getElementById('status');

	contact = {};

	// load contacts
	xhr('get', '/contacts/', undefined, function(response) {
		contact = response;

		Object.keys(contact).forEach(function(key) {
			var li = document.createElement('li');

			var span_name = document.createElement('span');
			var span_number = document.createElement('span');
			var button_call = document.createElement('button');
			var button_message = document.createElement('button');

			span_name.innerText = contact[key];
			span_number.innerText = key;

			button_call.innerText = 'Call';
			button_message.innerText = 'Message';

			button_call.addEventListener('click', function(ev) {
				window.call(key);
			});
			button_message.addEventListener('click', function(ev) {
				window.open(key);
			});

			li.appendChild(span_name);
			li.appendChild(span_number);
			li.appendChild(button_call);
			li.appendChild(button_message);

			contacts.appendChild(li);
		});
	});

	// setup callbacks
	xhr('get', '/browser', undefined, function(data) {
		// get number
		number = data.number;

		// get token
		token = data.token;

		// setup Twilio.Device
		Twilio.Device.setup(token);

		Twilio.Device.connect(function (conn) {
			state = 'connected';
			statusline.innerText = 'Connected.';
		});

		Twilio.Device.disconnect(function (conn) {
			state = 'idle';
			statusline.innerText = 'Dial a Number';
		});

		Twilio.Device.incoming(function (conn) {
			state = 'incoming';

			incoming = conn;

			// get from name
			from = conn.parameters.From;

			if (from in contact)
				from = contact[from];

			statusline.innerText = 'Incoming Call From ' + from;

			// open phone
			select('phone');
		});

		Twilio.Device.offline(function(device) {
			// get another token
			xhr('get', '/browser', undefined, function(data) {
				// get token
				token = data.token;

				// setup Twilio.Device
				Twilio.Device.setup(token);
			});
		});

		// setup message callbacks
		var messageUpdate = function() {
			var current = messageTime;
			var next = new Date().toISOString();

			xhr('get', '/msgs/?date_sent_after=' + current + '&to=' + number, undefined, function(data) {
				data.forEach(function(msg) {
					open(msg.from, current);
				});
			});

			xhr('get', '/msgs/?date_sent_after=' + current + '&from=' + number, undefined, function(data) {
				data.forEach(function(msg) {
					open(msg.to, current);
				});
			});

			messageTime = next;

			setTimeout(messageUpdate, 1000);
		};

		// initiate message updates
		messageUpdate();

		// mark online
		xhr('post', '/browser', {'online': true});
	});

	// select nothing
	select(null);

	// show body
	document.body.style.display = 'flex';
};

var unload = function() {
	// mark offline
	xhr('post', '/browser', {'online': false});
};

var open = function(number, date) {
	if (document.getElementById(number) === null) {
		// create new chat block
		var chat = document.createElement('div');
		chat.id = number;
		chat.classList.add('chat');

		var container = document.createElement('div');

		var input = document.createElement('input');
		input.type = 'text';
		input.placeholder = 'Enter Message Here...';

		chat.appendChild(container);
		chat.appendChild(input);

		main.appendChild(chat);
		conversations.push(chat);

		// create button
		var button = document.createElement('button');
		button.id = 'button_' + number;
		button.addEventListener('click', function(ev) { window.select(number) });

		buttons.insertBefore(button, buttons.firstChild);
	}

	base = '/msgs/?';

	if (date !== undefined)
		base += 'date_sent_after=' + date + '&';

	// load chat
	xhr('get', base + 'to=' + number, function(data) {
		xhr('get', base + 'from=' + number, function(dataInner) {
			// get all messages
			var messages = data.concat(dataInner);

			// sort by date
			messages.sort(function(left, right) {
				return new Date(right.date) - new Date(left.date);
			});

			// generate elements
			messages.forEach(function(message) {
				// create chat bubble
				var div = document.createElement('div');

				// set class based on whether this was sent or receieved
				if (message.from === number)
					div.classList.add('me');
				else
					div.classList.add('you');

				// get message time
				var date = new Date(message.date);

				// format time
				var time = document.createElement('time');
				time.innerText = '';
				time.innerText += date.getFullYear();
				time.innerText += ('0' + (date.Month() + 1)).slice(-2);
				time.innerText += ('0' + date.getDate()).slice(-2);
				time.innerText += ' ';
				time.innerText += ('0' + date.getHours()).slice(-2);
				time.innerText += ':';
				time.innerText += ('0' + date.getSeconds()).slice(-2);

				// add body
				var p = document.createElement('p');
				p.innerText = message.body;

				// join time and body into message
				div.appendChild(time);
				div.appendChild(p);

				// add message to chat window
				document.getElementById(number).children[0].appendChild(div);
			});

			// bring chat forward
			select(number);
		});
	});
};

var close = function(number) {
	if (conversations.indexOf(number) === -1)
		return;

	// remove chat block
	main.removeChild(conversations[number]);

	// bring last thing forward
	select(last);
};

var click = function(key) {
	if (state === 'connecting' || state === 'connected') {
		if (key === 'hangup') {
			hangup();
		}
		else if (key === 'dial') {
			// do nothing
		}
		else {
			connection.sendDigits(key);
		}
	}
	else if (state === 'idle') {
		if (key === 'hangup') {
			// do nothing
		}
		else if (key === 'dial') {
			// do nothing
		}
		else {
			statusline.innerText = key;
		}

		state = 'dialing';
	}
	else if (state === 'dialing') {
		if (key === 'dial') {
			call(statusline.innerText);
		}
		else if (key === 'hangup') {
			statusline.innerText = 'Dial a Number';

			state = 'idle';
		}
		else {
			statusline.innerText += key;
		}
	}
	else if (state === 'incoming') {
		if (key === 'dial') {
			incoming.accept();

			connection = incoming;
		}
		else if (key === 'hangup') {
			incoming.reject();
		}

		state = 'connected';
		status.innerText = 'Connected.';
	}
};

var call = function(number) {
	// update state
	state = 'connecting';

	// create connection
	connection = Twilio.Device.connect({'To': number});

	// call number
	select('phone');
};

var hangup = function() {
	// close phone
	select(last);

	// disconnect line
	Twilio.Device.disconnectAll();
};

var select = function(id) {
	if (id === 'toggle') {
		if (phone.style.display === 'none')
			// behave as though phone were selected
			id = 'phone';
		else
			// behave as though last were selected
			id = last;
	}

	if (id === 'phone') {
		// simply display phone
		phone.style.display = '';
	}
	else {
		// close all conversations
		conversations.forEach(function(element) {
			element.style.display = 'none';
		});

		// close phone and contacts
		contacts.style.display = 'none';
		phone.style.display = 'none';

		// display requested section
		if (id !== null)
			document.getElementById(id).style.display = '';
	}

	// disable all buttons
	for (var idx = 0; idx < button.length; idx++)
		button[idx].classList.remove('active');

	// mark respective button as active
	if (id !== null)
		document.getElementById('button_' + id).classList.add('active');

	if (id !== 'phone')
		last = id;
};

window.addEventListener('load', load);
window.addEventListener('unload', unload);
<|endoftext|>


<commit_before>/*global app*/
var Router = require('ampersand-router')
var ViewSwitcher = require('ampersand-view-switcher')

var HomePage = require('./pages/home')

var PageNotFound = require('./pages/notFound')

var Achievements = require('./pages/achievements/list')
var AchievementViewPage = require('./pages/achievements/view')

var LoginPage = require('./pages/auth/login')

var Partners = require('./pages/partners/list')

var Redeem = require('./pages/redeem/view')

var Sessions = require('./pages/sessions/list')
var SessionViewPage = require('./pages/sessions/view')

var Speakers = require('./pages/speakers/list')
var SpeakerViewPage = require('./pages/speakers/view')

var UserViewPage = require('./pages/users/view')
var MePage = require('./pages/users/me')
var UserEditPage = require('./pages/users/edit')

var log = require('bows')('router')
var fenixAuth = require('./auth/fenix')
var qs = require('qs')

var WebAppRouter = Router.extend({
  routes: {
    '': 'home',
    ':event': 'event',
    ':event/achievements': 'achievements',
    ':event/achievements/:id': 'achievementView',
    'auth/login?:query': 'fenixLogin',
    'auth/login': 'login',
    // 'partners': 'partners',
    // 'partners/:id': 'companyView',
    'redeem/:id': 'redeemCode',
    // 'sessions': 'sessions',
    // 'sessions/:id': 'sessionView',
    ':event/speakers': 'speakers',
    'users/:id': 'userView',
    'me': 'me',
    'me/edit': 'meEdit',
    'speakers/:id': 'speakerView',
    // 'stream': 'streamView',
    'sponsor': 'sponsor',
    '(*path)': 'catchAll'
  },

  execute: function (callback, args, name) {
    window.ga('send', 'pageview', window.location.pathname)

    window.scrollTo(0, 0)

    return Router.prototype.execute.apply(this, [callback, args, name])
  },

  // ------- ROUTE HANDLERS ---------
  home: function () {
    // this.trigger('page', new HomePage({
    //   model: app.me
    // }))
    window.location = '/'
  },

  event: function () {
    this.trigger('page', new HomePage({
      model: app.me
    }))
  },

  achievements: function () {
    this.trigger('page', new Achievements({
      collection: app.achievements
    }))
  },

  achievementView: function (id) {
    this.trigger('page', new AchievementViewPage({
      id: id
    }))
  },

  me: function () {
    if (!app.me || !app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new MePage({
      model: app.me
    }))
  },

  userView: function (id) {
    this.trigger('page', new UserViewPage({
      id: id
    }))

  },

  meEdit: function () {
    if (!app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new UserEditPage({
      model: app.me
    }))
  },

  login: function () {
    // if(app.me.authenticated) {
    //   return this.redirectTo('/')
    // }

    this.trigger('page', new LoginPage({
      model: app.me
    }))
  },

  fenixLogin: function (args) {
    if (sessionStorage['cannon-fenix-add'] === 'true') {
      this.me()
    } else {
      this.login()
    }
    args = qs.parse(args)
    if (args && Object.keys(args)[0] === 'code') {
      fenixAuth.requestAccessToken(args.code)
    }
  },

  partners: function () {
    this.trigger('page', new Partners({
      collection: app.partners
    }))
  },

  redeemCode: function (id) {
    if (!app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new Redeem({id: id}))
  },

  sessions: function () {
    this.trigger('page', new Sessions({
      collection: app.sessions
    }))
  },

  sessionView: function (id) {
    this.trigger('page', new SessionViewPage({
      id: id
    }))
  },

  sponsor: function () {
    window.open('/sponsor.html')
  },

  // speakers: function () {
  //   this.trigger('page', new Speakers({
  //     collection: app.speakers.current
  //   }))
  // },

  speakers: function () {
    this.navigate('/\#speakers', {trigger: false})
  },

  speakerView: function (id) {
    this.trigger('page', new SpeakerViewPage({
      id: id
    }))
  },

  catchAll: function () {
    this.trigger('page', new PageNotFound())
  }
})

module.exports = WebAppRouter
<commit_msg>uncomment a lot of client routes<commit_after>/*global app*/
var Router = require('ampersand-router')

var HomePage = require('./pages/home')

var PageNotFound = require('./pages/notFound')

var Achievements = require('./pages/achievements/list')
var AchievementViewPage = require('./pages/achievements/view')

var LoginPage = require('./pages/auth/login')

var Partners = require('./pages/partners/list')

var Redeem = require('./pages/redeem/view')

var Sessions = require('./pages/sessions/list')
var SessionViewPage = require('./pages/sessions/view')

var Speakers = require('./pages/speakers/list')
var SpeakerViewPage = require('./pages/speakers/view')

var UserViewPage = require('./pages/users/view')
var MePage = require('./pages/users/me')
var UserEditPage = require('./pages/users/edit')

var log = require('bows')('router')
var fenixAuth = require('./auth/fenix')
var qs = require('qs')

var WebAppRouter = Router.extend({
  routes: {
    '': 'home',
    ':event': 'event',
    ':event/achievements': 'achievements',
    ':event/achievements/:id': 'achievementView',
    'auth/login?:query': 'fenixLogin',
    'auth/login': 'login',
    ':event/partners': 'partners',
    'partners/:id': 'companyView',
    'redeem/:id': 'redeemCode',
    ':event/sessions': 'sessions',
    ':event/sessions/:id': 'sessionView',
    ':event/speakers': 'speakers',
    'users/:id': 'userView',
    'me': 'me',
    'me/edit': 'meEdit',
    'speakers/:id': 'speakerView',
    // 'stream': 'streamView',
    'sponsor': 'sponsor',
    '(*path)': 'catchAll'
  },

  execute: function (callback, args, name) {
    window.ga('send', 'pageview', window.location.pathname)

    window.scrollTo(0, 0)

    return Router.prototype.execute.apply(this, [callback, args, name])
  },

  // ------- ROUTE HANDLERS ---------
  home: function () {
    // this.trigger('page', new HomePage({
    //   model: app.me
    // }))
    window.location = '/'
  },

  event: function (event) {
    this.trigger('page', new HomePage({
      event: event,
      model: app.me
    }))
  },

  achievements: function (event) {
    this.trigger('page', new Achievements({
      event: event,
      collection: app.achievements
    }))
  },

  achievementView: function (event, id) {
    this.trigger('page', new AchievementViewPage({
      event: event,
      id: id
    }))
  },

  me: function () {
    if (!app.me || !app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new MePage({
      model: app.me
    }))
  },

  userView: function (id) {
    this.trigger('page', new UserViewPage({
      id: id
    }))
  },

  meEdit: function () {
    if (!app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new UserEditPage({
      model: app.me
    }))
  },

  login: function () {
    // if(app.me.authenticated) {
    //   return this.redirectTo('/')
    // }

    this.trigger('page', new LoginPage({
      model: app.me
    }))
  },

  fenixLogin: function (args) {
    if (window.sessionStorage['cannon-fenix-add'] === 'true') {
      this.me()
    } else {
      this.login()
    }
    args = qs.parse(args)
    if (args && Object.keys(args)[0] === 'code') {
      fenixAuth.requestAccessToken(args.code)
    }
  },

  partners: function (event) {
    this.trigger('page', new Partners({
      event: event,
      collection: app.partners
    }))
  },

  redeemCode: function (event, id) {
    if (!app.me.authenticated) {
      return app.navigateToLogin()
    }

    this.trigger('page', new Redeem({
      event: event,
      id: id
    }))
  },

  sessions: function (event) {
    this.trigger('page', new Sessions({
      event: event,
      collection: app.sessions
    }))
  },

  sessionView: function (event, id) {
    this.trigger('page', new SessionViewPage({
      event: event,
      id: id
    }))
  },

  sponsor: function () {
    window.location = '/sponsor'
  },

  speakers: function (event) {
    this.trigger('page', new Speakers({
      event: event,
      collection: app.speakers.current
    }))
  },

  speakerView: function (id) {
    this.trigger('page', new SpeakerViewPage({
      id: id
    }))
  },

  catchAll: function () {
    this.trigger('page', new PageNotFound())
  }
})

module.exports = WebAppRouter
<|endoftext|>


<commit_before>function searchPage() {
  var $page = $('#search-page')
  var $input = $page.find('.query')
  var $button = $page.find('button.search')
  var $filters = $page.find('.filters input[type=checkbox]')
  var $results = $page.find('.results')
  var $noResults = $page.find('.no-results')
  var $noMoreResults = $page.find('.no-more-results')
  var $loading = $page.find('.loading')
  var $detailTemplate = $('#templates > .search-result-details').detach()
  var $newClassificationButton = $page.find('.new-classification button')

  var state = { q:'', page: 0 }

  $page.on('show', function(e, q, filters, programId) {
    $input.val(q || '').trigger('reset')
    setFilters(filters)
    queryChanged(q || '')
    loadUntil(programId)
  })

  $button.click(function() { $input.trigger('fire') })
  $filters.on('change', function() { $input.trigger('fire') })

  $(window).on('scroll', function() {
    if (!$page.is(':visible')) return
    if ($loading.is(':visible') || $noResults.is(':visible') || $noMoreResults.is(':visible')) return
    if($(document).height() - $(window).scrollTop() - $(window).height() < 100) {
      state.page++
      load()
    }
  })

  $input.throttledInput(function() {
    queryChanged($input.val().trim())
    updateLocationHash()
    load()
  })

  $('input[name="new-classification-type"]').select2({
    data: [
      {id: 1, text: 'Elokuva'},
      {id: 4, text: 'Extra'},
      {id: 5, text: 'Trailer'}
    ]
  }).select2('val', 1)

  $newClassificationButton.click(function() {
    var programType = $('input[name="new-classification-type"]').select2('val')
    $.post('/programs/new', JSON.stringify({'program-type': programType})).done(function(program) {
      $('body').children('.page').hide()
      $('#classification-page').trigger('show', program._id).show()
    })
  })

  function queryChanged(q) {
    state = { q:q, page: 0 }
    $noResults.add($noMoreResults).hide()
  }

  function loadUntil(selectedProgramId) {
    load(function() {
      if (!selectedProgramId) {
        updateLocationHash()
        return
      }
      var $selected = $results.find('.result[data-id='+selectedProgramId+']')
      if ($selected.length > 0) {
        openDetail($selected, false)
        var top = $selected.offset().top - 25
        $('body,html').animate({ scrollTop: top })
      } else if (state.page < 20) {
        state.page++
        loadUntil(selectedProgramId)
      }
    })
  }

  function load(callback) {
    $loading.show()
    var url = '/programs/search/'+encodeURIComponent(state.q)
    var data = $.param({ page:state.page, filters:currentFilters() })
    state.jqXHR = $.get(url, data).done(function(results, status, jqXHR) {
      if (state.jqXHR != jqXHR) return
      $noResults.toggle(state.page == 0 && results.length == 0)
      $noMoreResults.toggle((state.page > 0 || results.length > 0) && results.length < 100)
      if (state.page == 0) $results.empty()
      $results.append(results.map(function(p) { return render(p, state.q) }))
      $loading.hide()
      if (callback) callback()
    })
  }

  function currentFilters() {
    return $filters.filter(':checked')
      .map(function() { return $(this).data('type') })
      .toArray().join(',').split(',')
  }

  function setFilters(filterString) {
    $filters.each(function() {
      $(this).prop('checked', filterString && filterString.indexOf($(this).data('id')) >= 0)
    })
  }

  $results.on('click', '.result', function() {
    if ($(this).hasClass('selected')) {
      updateLocationHash()
      closeDetail()
    } else {
      closeDetail()
      openDetail($(this), true)
    }
  })

  function openDetail($row, animate) {
    var p = $row.data('program')
    updateLocationHash(p._id)
    var $details = renderDetails(p)
    $row.addClass('selected').after($details)
    animate ? $details.slideDown() : $details.show()
  }

  function closeDetail() {
    $results.find('.result.selected').removeClass('selected')
    $results.find('.search-result-details').slideUp(function() { $(this).remove() }).end()
  }

  $results.on('click', 'button.reclassify', function(e) {
    var id = $(this).parents('.search-result-details').data('id')
    $.post('/programs/' + id + '/reclassification').done(function(program) {
      $('body').children('.page').hide()
      $('#classification-page').trigger('show', program._id).show()
    })
  })
  $results.on('click', 'button.continue-classification', function(e) {
    var id = $(this).parents('.search-result-details').data('id')
    $('body').children('.page').hide()
    $('#classification-page').trigger('show', id).show()
  })

  function updateLocationHash(selectedProgramId) {
    var filters = $filters.filter(':checked').map(function() { return $(this).data('id') }).toArray().join('')
    location.hash = '#haku/' + encodeURIComponent(state.q) + '/' + filters + '/' + (selectedProgramId || '')
  }

  function render(p, query) {
    var c = p.classifications[0]
    var queryParts = (query || '').trim().toLowerCase().split(/\s+/)
    return $('<div>', { class:'result', 'data-id': p._id })
      .data('program', p)
      .append($('<span>').text(name(p)).highlight(queryParts, { beginningsOnly: true, caseSensitive: false }))
      .append($('<span>').text(countryAndYear(p)))
      .append($('<span>').text(classification.ageLimit(c)))
      .append($('<span>').text(enums.programType[p['program-type']].fi))
      .append($('<span>').text(enums.util.isGameType(p) ? p.gameFormat || '': duration(c)))

    function name(p) {
      return _.compact([p.name[0], utils.seasonEpisodeCode(p)]).join(' ')
    }

    function countryAndYear(p) {
      var s = _([enums.util.toCountryString(p.country), p.year]).compact().join(', ')
      return s == '' ? s : '('+s+')'
    }

    function duration(c) {
      if (!c || !c.duration) return ''
      var match = c.duration.match(/(?:(\d+)?:)?(\d+):(\d+)$/)
      if (!match) return c.duration
      match.shift()
      return _.chain(match).map(suffixify).compact().join(' ')

      function suffixify(x, ii) {
        if (!x) return x
        var int = parseInt(x)
        if (!int) return ''
        if (ii == 0) return int + ' h'
        if (ii == 1) return int + ' min'
        if (ii == 2) return int + ' s'
        return x
      }
    }
  }

  function renderDetails(p) {
    var names = { n: p.name.join(', '), fi: p['name-fi'].join(', '), sv: p['name-sv'].join(', '), other: p['name-other'].join(', ')}
    var series = p.series && p.series.name || undefined
    var episode = utils.seasonEpisodeCode(p)
    var classificationStatusText = classification.fullStatus(p.classifications).map(function(t) { return $('<span>').text(t) })
    var $e = $detailTemplate.clone()
      .data('id', p._id)
      .find('.primary-name').text(p.name[0]).end()
      .find('.name').text(names.n).end()
      .find('.name-fi').text(names.fi).end()
      .find('.name-sv').text(names.sv).prev().toggleClass('hide', !names.sv).end().end()
      .find('.name-other').text(names.other).prev().toggleClass('hide', !names.other).end().end()
      .find('.series').text(series).prev().toggleClass('hide', !series).end().end()
      .find('.episode').text(episode).prev().toggleClass('hide', !episode).end().end()
      .find('.country').text(enums.util.toCountryString(p.country)).end()
      .find('.year').text(p.year).end()
      .find('.production-companies').text(p['production-companies'].join(', ')).end()
      .find('.genre').text(p.genre.join(', ') || p['legacy-genre'].join(', ')).end()
      .find('.directors').text(p.directors.join(', ')).end()
      .find('.actors').text(p.actors.join(', ')).end()
      .find('.synopsis').text(p.synopsis).end()
      .find('.status').html(classificationStatusText).end()

    var c = classification.mostValid(p.classifications)
    if (c) {
      var summary = classification.summary(p, c)
      $e.find('.agelimit').attr('src', ageLimitIcon(summary)).end()
        .find('.warnings').html(warningIcons(summary)).end()
        .find('.buyer').text(c.buyer && c.buyer.name || '').end()
        .find('.billing').text(c.billing && c.billing.name || '').end()
        .find('.format').text(enums.util.isGameType(p) && p.gameFormat || c.format).end()
        .find('.duration').text(c.duration).end()
        .find('.criteria').html(renderClassificationCriteria(c)).end()
    }

    var head = p.classifications[0]
    var canContinue = head && head.status == 'in_process' && (hasRole('kavi') || !head.author || head.author._id == user._id)
    var canReclassify = !canContinue && (hasRole('kavi') || !head || (head.status != 'registered' && head.status != 'in_process'))
    $e.find('button.continue-classification').toggle(canContinue)
    $e.find('button.reclassify').toggle(canReclassify)

    return $e
  }

  function renderClassificationCriteria(c) {
    if (!c.criteria) return ''
    return c.criteria.map(function(id) {
      var cr = enums.classificationCriteria[id - 1]
      var category = enums.classificationCategoriesFI[cr.category]
      return $('<div>')
        .append($('<label>').text(category + ' ('+cr.id+')'))
        .append($('<span>').text(c['criteria-comments'] && c['criteria-comments'][cr.id] || ''))
    })
  }
}
<commit_msg>Booleanify<commit_after>function searchPage() {
  var $page = $('#search-page')
  var $input = $page.find('.query')
  var $button = $page.find('button.search')
  var $filters = $page.find('.filters input[type=checkbox]')
  var $results = $page.find('.results')
  var $noResults = $page.find('.no-results')
  var $noMoreResults = $page.find('.no-more-results')
  var $loading = $page.find('.loading')
  var $detailTemplate = $('#templates > .search-result-details').detach()
  var $newClassificationButton = $page.find('.new-classification button')

  var state = { q:'', page: 0 }

  $page.on('show', function(e, q, filters, programId) {
    $input.val(q || '').trigger('reset')
    setFilters(filters)
    queryChanged(q || '')
    loadUntil(programId)
  })

  $button.click(function() { $input.trigger('fire') })
  $filters.on('change', function() { $input.trigger('fire') })

  $(window).on('scroll', function() {
    if (!$page.is(':visible')) return
    if ($loading.is(':visible') || $noResults.is(':visible') || $noMoreResults.is(':visible')) return
    if($(document).height() - $(window).scrollTop() - $(window).height() < 100) {
      state.page++
      load()
    }
  })

  $input.throttledInput(function() {
    queryChanged($input.val().trim())
    updateLocationHash()
    load()
  })

  $('input[name="new-classification-type"]').select2({
    data: [
      {id: 1, text: 'Elokuva'},
      {id: 4, text: 'Extra'},
      {id: 5, text: 'Trailer'}
    ]
  }).select2('val', 1)

  $newClassificationButton.click(function() {
    var programType = $('input[name="new-classification-type"]').select2('val')
    $.post('/programs/new', JSON.stringify({'program-type': programType})).done(function(program) {
      $('body').children('.page').hide()
      $('#classification-page').trigger('show', program._id).show()
    })
  })

  function queryChanged(q) {
    state = { q:q, page: 0 }
    $noResults.add($noMoreResults).hide()
  }

  function loadUntil(selectedProgramId) {
    load(function() {
      if (!selectedProgramId) {
        updateLocationHash()
        return
      }
      var $selected = $results.find('.result[data-id='+selectedProgramId+']')
      if ($selected.length > 0) {
        openDetail($selected, false)
        var top = $selected.offset().top - 25
        $('body,html').animate({ scrollTop: top })
      } else if (state.page < 20) {
        state.page++
        loadUntil(selectedProgramId)
      }
    })
  }

  function load(callback) {
    $loading.show()
    var url = '/programs/search/'+encodeURIComponent(state.q)
    var data = $.param({ page:state.page, filters:currentFilters() })
    state.jqXHR = $.get(url, data).done(function(results, status, jqXHR) {
      if (state.jqXHR != jqXHR) return
      $noResults.toggle(state.page == 0 && results.length == 0)
      $noMoreResults.toggle((state.page > 0 || results.length > 0) && results.length < 100)
      if (state.page == 0) $results.empty()
      $results.append(results.map(function(p) { return render(p, state.q) }))
      $loading.hide()
      if (callback) callback()
    })
  }

  function currentFilters() {
    return $filters.filter(':checked')
      .map(function() { return $(this).data('type') })
      .toArray().join(',').split(',')
  }

  function setFilters(filterString) {
    $filters.each(function() {
      $(this).prop('checked', filterString && filterString.indexOf($(this).data('id')) >= 0)
    })
  }

  $results.on('click', '.result', function() {
    if ($(this).hasClass('selected')) {
      updateLocationHash()
      closeDetail()
    } else {
      closeDetail()
      openDetail($(this), true)
    }
  })

  function openDetail($row, animate) {
    var p = $row.data('program')
    updateLocationHash(p._id)
    var $details = renderDetails(p)
    $row.addClass('selected').after($details)
    animate ? $details.slideDown() : $details.show()
  }

  function closeDetail() {
    $results.find('.result.selected').removeClass('selected')
    $results.find('.search-result-details').slideUp(function() { $(this).remove() }).end()
  }

  $results.on('click', 'button.reclassify', function(e) {
    var id = $(this).parents('.search-result-details').data('id')
    $.post('/programs/' + id + '/reclassification').done(function(program) {
      $('body').children('.page').hide()
      $('#classification-page').trigger('show', program._id).show()
    })
  })
  $results.on('click', 'button.continue-classification', function(e) {
    var id = $(this).parents('.search-result-details').data('id')
    $('body').children('.page').hide()
    $('#classification-page').trigger('show', id).show()
  })

  function updateLocationHash(selectedProgramId) {
    var filters = $filters.filter(':checked').map(function() { return $(this).data('id') }).toArray().join('')
    location.hash = '#haku/' + encodeURIComponent(state.q) + '/' + filters + '/' + (selectedProgramId || '')
  }

  function render(p, query) {
    var c = p.classifications[0]
    var queryParts = (query || '').trim().toLowerCase().split(/\s+/)
    return $('<div>', { class:'result', 'data-id': p._id })
      .data('program', p)
      .append($('<span>').text(name(p)).highlight(queryParts, { beginningsOnly: true, caseSensitive: false }))
      .append($('<span>').text(countryAndYear(p)))
      .append($('<span>').text(classification.ageLimit(c)))
      .append($('<span>').text(enums.programType[p['program-type']].fi))
      .append($('<span>').text(enums.util.isGameType(p) ? p.gameFormat || '': duration(c)))

    function name(p) {
      return _.compact([p.name[0], utils.seasonEpisodeCode(p)]).join(' ')
    }

    function countryAndYear(p) {
      var s = _([enums.util.toCountryString(p.country), p.year]).compact().join(', ')
      return s == '' ? s : '('+s+')'
    }

    function duration(c) {
      if (!c || !c.duration) return ''
      var match = c.duration.match(/(?:(\d+)?:)?(\d+):(\d+)$/)
      if (!match) return c.duration
      match.shift()
      return _.chain(match).map(suffixify).compact().join(' ')

      function suffixify(x, ii) {
        if (!x) return x
        var int = parseInt(x)
        if (!int) return ''
        if (ii == 0) return int + ' h'
        if (ii == 1) return int + ' min'
        if (ii == 2) return int + ' s'
        return x
      }
    }
  }

  function renderDetails(p) {
    var names = { n: p.name.join(', '), fi: p['name-fi'].join(', '), sv: p['name-sv'].join(', '), other: p['name-other'].join(', ')}
    var series = p.series && p.series.name || undefined
    var episode = utils.seasonEpisodeCode(p)
    var classificationStatusText = classification.fullStatus(p.classifications).map(function(t) { return $('<span>').text(t) })
    var $e = $detailTemplate.clone()
      .data('id', p._id)
      .find('.primary-name').text(p.name[0]).end()
      .find('.name').text(names.n).end()
      .find('.name-fi').text(names.fi).end()
      .find('.name-sv').text(names.sv).prev().toggleClass('hide', !names.sv).end().end()
      .find('.name-other').text(names.other).prev().toggleClass('hide', !names.other).end().end()
      .find('.series').text(series).prev().toggleClass('hide', !series).end().end()
      .find('.episode').text(episode).prev().toggleClass('hide', !episode).end().end()
      .find('.country').text(enums.util.toCountryString(p.country)).end()
      .find('.year').text(p.year).end()
      .find('.production-companies').text(p['production-companies'].join(', ')).end()
      .find('.genre').text(p.genre.join(', ') || p['legacy-genre'].join(', ')).end()
      .find('.directors').text(p.directors.join(', ')).end()
      .find('.actors').text(p.actors.join(', ')).end()
      .find('.synopsis').text(p.synopsis).end()
      .find('.status').html(classificationStatusText).end()

    var c = classification.mostValid(p.classifications)
    if (c) {
      var summary = classification.summary(p, c)
      $e.find('.agelimit').attr('src', ageLimitIcon(summary)).end()
        .find('.warnings').html(warningIcons(summary)).end()
        .find('.buyer').text(c.buyer && c.buyer.name || '').end()
        .find('.billing').text(c.billing && c.billing.name || '').end()
        .find('.format').text(enums.util.isGameType(p) && p.gameFormat || c.format).end()
        .find('.duration').text(c.duration).end()
        .find('.criteria').html(renderClassificationCriteria(c)).end()
    }

    var head = p.classifications[0]
    var canContinue = head && head.status == 'in_process' && (hasRole('kavi') || !head.author || head.author._id == user._id)
    var canReclassify = !canContinue && (hasRole('kavi') || !head || (head.status != 'registered' && head.status != 'in_process'))
    $e.find('button.continue-classification').toggle(!!canContinue)
    $e.find('button.reclassify').toggle(!!canReclassify)

    return $e
  }

  function renderClassificationCriteria(c) {
    if (!c.criteria) return ''
    return c.criteria.map(function(id) {
      var cr = enums.classificationCriteria[id - 1]
      var category = enums.classificationCategoriesFI[cr.category]
      return $('<div>')
        .append($('<label>').text(category + ' ('+cr.id+')'))
        .append($('<span>').text(c['criteria-comments'] && c['criteria-comments'][cr.id] || ''))
    })
  }
}
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Sat Sep 20 2014 20:50:04 GMT+0000 (UTC)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'bower_components/angular/angular.js',
      'bower_components/angular-classy/angular-classy.js',
      'classy-extends.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'test/unit/*.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [
      'Chrome'
      //'PhantomJS'
    ],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};
<commit_msg>change karma config back<commit_after>// Karma configuration
// Generated on Sat Sep 20 2014 20:50:04 GMT+0000 (UTC)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'bower_components/angular/angular.js',
      'bower_components/angular-classy/angular-classy.js',
      'classy-extends.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'test/unit/*.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [
      //'Chrome',
      'PhantomJS'
    ],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true
  });
};
<|endoftext|>


<commit_before>/*jshint loopfunc: true, strict: false */
/*global setTimeout */

/*jshint -W098 */
var p = (function () {
  /*jshint +W098 */

  var task = setTimeout;

  function isFunction(value) {
    return typeof value === 'function';
  }

  function resolutionProcedure(promise, x, resolve, reject) {
    if (promise === x) {
      throw TypeError();
    }
    if ((x && typeof x === 'object') || isFunction(x)) {
      var called = 0;
      try {
        var then = x.then;
        if (isFunction(then)) {
          then.call(x, function (y) {
            if (called) {
              return;
            }
            called = 1;
            resolutionProcedure(promise, y, resolve, reject);
          }, function (r) {
            if (called) {
              return;
            }
            called = 1;
            reject(r);
          });
        } else {
          resolve(x);
        }
      } catch (e) {
        if (!called) {
          reject(e);
        }
      }
    } else {
      resolve(x);
    }
  }

  var FULFILLED = 1;
  var REJECTED = 2;

  function defer() {
    var state;
    var valueOrReason;
    var onFulfilleds;
    var onRejecteds;
    var promises;
    var resolves;
    var rejects;
    function empty() {
      onFulfilleds = [];
      onRejecteds = [];
      promises = [];
      resolves = [];
      rejects = [];
    }
    empty();
    function iterateCallbacks(callbacks, iteratee) {
      for (var i = 0; i < callbacks.length; i += 1) {
        (function (callback, promise, resolve, reject) {
          task(function () {
            iteratee(callback, promise, resolve, reject);
          });
        }(callbacks[i], promises[i], resolves[i], rejects[i]));
      }
      empty();
    }
    function callOnFulfilleds() {
      iterateCallbacks(onFulfilleds, function (onFulfilled, promise, resolve, reject) {
        try {
          var x = isFunction(onFulfilled) ? onFulfilled(valueOrReason) : valueOrReason;
          resolutionProcedure(promise, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }
    function callOnRejecteds() {
      iterateCallbacks(onRejecteds, function (onRejected, promise, resolve, reject) {
        try {
          if (isFunction(onRejected)) {
            var x = onRejected(valueOrReason);
            resolutionProcedure(promise, x, resolve, reject);
          } else {
            reject(valueOrReason);
          }
        } catch (e) {
          reject(e);
        }
      });
    }
    return {
      promise: {
        then: function (onFulfilled, onRejected) {
          onFulfilleds.push(onFulfilled);
          onRejecteds.push(onRejected);
          var deferred = defer();
          promises.push(deferred.promise);
          resolves.push(deferred.resolve);
          rejects.push(deferred.reject);
          if (state === FULFILLED) {
            callOnFulfilleds();
          }
          if (state === REJECTED) {
            callOnRejecteds();
          }
          return deferred.promise;
        }
      },
      resolve: function (value) {
        if (state) {
          return;
        }
        state = FULFILLED;
        valueOrReason = value;
        callOnFulfilleds();
      },
      reject: function (reason) {
        if (state) {
          return;
        }
        state = REJECTED;
        valueOrReason = reason;
        callOnRejecteds();
      }
    };
  }

  return {
    defer: defer
  };

}());
<commit_msg>Golf pending objects to array.<commit_after>/*jshint loopfunc: true, strict: false */
/*global setTimeout */

/*jshint -W098 */
var p = (function () {
  /*jshint +W098 */

  var task = setTimeout;

  function isFunction(value) {
    return typeof value === 'function';
  }

  function resolutionProcedure(promise, x, resolve, reject) {
    if (promise === x) {
      throw TypeError();
    }
    if ((x && typeof x === 'object') || isFunction(x)) {
      var called = 0;
      try {
        var then = x.then;
        if (isFunction(then)) {
          then.call(x, function (y) {
            if (called) {
              return;
            }
            called = 1;
            resolutionProcedure(promise, y, resolve, reject);
          }, function (r) {
            if (called) {
              return;
            }
            called = 1;
            reject(r);
          });
        } else {
          resolve(x);
        }
      } catch (e) {
        if (!called) {
          reject(e);
        }
      }
    } else {
      resolve(x);
    }
  }

  var FULFILLED = 1;
  var REJECTED = 2;

  function defer() {
    var state;
    var valueOrReason;
    var pending = [];
    function iteratePending(offset, iteratee) {
      var p;
      while ((p = pending.shift())) {
        (function (callback, promise, resolve, reject) {
          task(function () {
            iteratee(callback, promise, resolve, reject);
          });
        }(p[offset], p[2], p[3], p[4]));
      }
    }
    function callOnFulfilleds() {
      iteratePending(0, function (onFulfilled, promise, resolve, reject) {
        try {
          var x = isFunction(onFulfilled) ? onFulfilled(valueOrReason) : valueOrReason;
          resolutionProcedure(promise, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }
    function callOnRejecteds() {
      iteratePending(1, function (onRejected, promise, resolve, reject) {
        try {
          if (isFunction(onRejected)) {
            var x = onRejected(valueOrReason);
            resolutionProcedure(promise, x, resolve, reject);
          } else {
            reject(valueOrReason);
          }
        } catch (e) {
          reject(e);
        }
      });
    }
    return {
      promise: {
        then: function (onFulfilled, onRejected) {
          var deferred = defer();
          pending.push([
            onFulfilled,
            onRejected,
            deferred.promise,
            deferred.resolve,
            deferred.reject
          ]);
          if (state === FULFILLED) {
            callOnFulfilleds();
          }
          if (state === REJECTED) {
            callOnRejecteds();
          }
          return deferred.promise;
        }
      },
      resolve: function (value) {
        if (state) {
          return;
        }
        state = FULFILLED;
        valueOrReason = value;
        callOnFulfilleds();
      },
      reject: function (reason) {
        if (state) {
          return;
        }
        state = REJECTED;
        valueOrReason = reason;
        callOnRejecteds();
      }
    };
  }

  return {
    defer: defer
  };

}());
<|endoftext|>


<commit_before>const saucelabsBrowsers = require('./saucelabs-browsers').browsers,
  path = require('path'),
  browsers = ['PhantomJS'],
  RIOT_WITH_COMPILER_PATH = path.resolve('dist', 'riot', 'riot+compiler.es6.js'),
  RIOT_PATH = path.resolve('dist', 'riot', 'riot.es6.js'),
  // split the riot+compiler tests from the normal riot core tests
  testFiles = `./specs/${process.env.TEST_FOLDER}/**/*.spec.js`,
  preprocessors = {}

// run the tests only on the saucelabs browsers
if (process.env.SAUCELABS) {
  browsers = Object.keys(saucelabsBrowsers)
}

module.exports = function(conf) {

  preprocessors[testFiles] = ['rollup']

  conf.set({
    basePath: '',
    autoWatch: true,
    frameworks: ['mocha'],
    plugins: [
      'karma-mocha',
      'karma-coverage',
      'karma-rollup-preprocessor',
      'karma-phantomjs-launcher',
      'karma-chrome-launcher',
      'karma-sauce-launcher'
    ],
    proxies: {
      '/tag/': '/base/tag/'
    },
    files: [
      '../node_modules/chai/chai.js',
      '../node_modules/sinon/pkg/sinon.js',
      '../node_modules/sinon-chai/lib/sinon-chai.js',
      {
        pattern: 'tag/*.tag',
        served: true,
        included: false
      },
      {
        pattern: '../dist/**/*.js',
        served: true,
        included: false
      },
      testFiles
    ],
    concurrency: 2,
    sauceLabs: {
      build: 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')',
      tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER,
      testName: 'riotjs',
      startConnect: true,
      recordVideo: false,
      recordScreenshots: false
    },
    captureTimeout: 300000,
    browserNoActivityTimeout: 300000,
    browserDisconnectTolerance: 2,
    customLaunchers: saucelabsBrowsers,
    browsers: browsers,

    reporters: ['progress', 'saucelabs', 'coverage'],
    preprocessors: preprocessors,

    rollupPreprocessor: {
      // use our default rollup plugins adding also the riot plugin
      // to import dinamically the tags
      rollup: {
        plugins: [
          require('rollup-plugin-alias')({
            'riot+compiler': RIOT_WITH_COMPILER_PATH,
            riot: RIOT_PATH
          }),
          require('rollup-plugin-riot')({
            riotPath: RIOT_PATH
          })
        ].concat(require('../config/defaults').plugins)
      },
      bundle: {
        format: 'umd'
        // sourceMap: 'inline' TODO: enable the sourcemaps in the compiler
      }
    },

    coverageReporter: {
      dir: '../coverage',
      reporters: [{
        type: 'lcov',
        subdir: 'report-lcov'
      }]
    },

    singleRun: true
  })
}
<commit_msg>removed: the dist folder from the tests<commit_after>const saucelabsBrowsers = require('./saucelabs-browsers').browsers,
  path = require('path'),
  browsers = ['PhantomJS'],
  RIOT_WITH_COMPILER_PATH = path.resolve('dist', 'riot', 'riot+compiler.es6.js'),
  RIOT_PATH = path.resolve('dist', 'riot', 'riot.es6.js'),
  // split the riot+compiler tests from the normal riot core tests
  testFiles = `./specs/${process.env.TEST_FOLDER}/**/*.spec.js`,
  preprocessors = {}

// run the tests only on the saucelabs browsers
if (process.env.SAUCELABS) {
  browsers = Object.keys(saucelabsBrowsers)
}

module.exports = function(conf) {

  preprocessors[testFiles] = ['rollup']

  conf.set({
    basePath: '',
    autoWatch: true,
    frameworks: ['mocha'],
    plugins: [
      'karma-mocha',
      'karma-coverage',
      'karma-rollup-preprocessor',
      'karma-phantomjs-launcher',
      'karma-chrome-launcher',
      'karma-sauce-launcher'
    ],
    proxies: {
      '/tag/': '/base/tag/'
    },
    files: [
      '../node_modules/chai/chai.js',
      '../node_modules/sinon/pkg/sinon.js',
      '../node_modules/sinon-chai/lib/sinon-chai.js',
      {
        pattern: 'tag/*.tag',
        served: true,
        included: false
      },
      testFiles
    ],
    concurrency: 2,
    sauceLabs: {
      build: 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')',
      tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER,
      testName: 'riotjs',
      startConnect: true,
      recordVideo: false,
      recordScreenshots: false
    },
    captureTimeout: 300000,
    browserNoActivityTimeout: 300000,
    browserDisconnectTolerance: 2,
    customLaunchers: saucelabsBrowsers,
    browsers: browsers,

    reporters: ['progress', 'saucelabs', 'coverage'],
    preprocessors: preprocessors,

    rollupPreprocessor: {
      // use our default rollup plugins adding also the riot plugin
      // to import dinamically the tags
      rollup: {
        plugins: [
          require('rollup-plugin-alias')({
            'riot+compiler': RIOT_WITH_COMPILER_PATH,
            riot: RIOT_PATH
          }),
          require('rollup-plugin-riot')({
            riotPath: RIOT_PATH
          })
        ].concat(require('../config/defaults').plugins)
      },
      bundle: {
        format: 'umd'
        // sourceMap: 'inline' TODO: enable the sourcemaps in the compiler
      }
    },

    coverageReporter: {
      dir: '../coverage',
      reporters: [{
        type: 'lcov',
        subdir: 'report-lcov'
      }]
    },

    singleRun: true
  })
}
<|endoftext|>


<commit_before>var chessground = require('chessground');
var opposite = chessground.util.opposite;
var data = require('./data');
var analyse = require('./analyse');
var ground = require('./ground');
var keyboard = require('./keyboard');
var treePath = require('./path');
var actionMenu = require('./actionMenu').controller;
var autoplay = require('./autoplay');
var control = require('./control');
var promotion = require('./promotion');
var util = require('./util');
var throttle = require('./util').throttle;
var socket = require('./socket');
var forecastCtrl = require('./forecast/forecastCtrl');
var cevalCtrl = require('./ceval/cevalCtrl');
var router = require('game').router;
var game = require('game').game;
var m = require('mithril');

module.exports = function(opts) {

  this.data = data({}, opts.data);
  this.userId = opts.userId;
  this.ongoing = !util.synthetic(this.data) && game.playable(this.data);

  this.analyse = new analyse(this.data.steps);
  this.actionMenu = new actionMenu();
  this.autoplay = new autoplay(this);

  var initialPath = opts.path ? treePath.read(opts.path) : treePath.default(this.analyse.firstPly());
  if (initialPath[0].ply >= this.data.steps.length)
    initialPath = treePath.default(this.data.steps.length - 1);

  this.vm = {
    path: initialPath,
    pathStr: treePath.write(initialPath),
    initialPathStr: '' + opts.data.path,
    step: null,
    cgConfig: null,
    comments: true,
    flip: false
  };

  this.flip = function() {
    this.vm.flip = !this.vm.flip;
    this.chessground.set({
      orientation: this.vm.flip ? this.data.opponent.color : this.data.player.color
    });
  }.bind(this);

  this.togglePlay = function(delay) {
    this.autoplay.toggle(delay);
    this.actionMenu.open = false;
  }.bind(this);

  var showGround = function() {
    var s;
    try {
      s = this.analyse.getStep(this.vm.path);
    } catch (e) {
      console.log(e);
    }
    if (!s) {
      this.vm.path = treePath.default(this.analyse.firstPly());
      this.vm.pathStr = treePath.write(this.vm.path);
      s = this.analyse.getStep(this.vm.path);
    }
    var color = s.ply % 2 === 0 ? 'white' : 'black';
    var dests = util.readDests(s.dests);
    var config = {
      fen: s.fen,
      turnColor: color,
      movable: {
        color: dests && Object.keys(dests).length > 0 ? color : null,
        dests: dests || {}
      },
      check: s.check,
      lastMove: s.uci ? [s.uci.substr(0, 2), s.uci.substr(2, 2)] : null,
    };
    if (!dests && !s.check) {
      // premove while dests are loading from server
      // can't use when in check because it highlights the wrong king
      config.turnColor = opposite(color);
      config.movable.color = color;
    }
    this.vm.step = s;
    this.vm.cgConfig = config;
    if (!this.chessground)
      this.chessground = ground.make(this.data, config, userMove);
    this.chessground.set(config);
    if (opts.onChange) opts.onChange(config.fen, this.vm.path);
    if (!dests) getDests();
    setAutoShapesFromEval();
  }.bind(this);

  var getDests = throttle(200, false, function() {
    if (this.vm.step.dests) return;
    this.socket.sendAnaDests({
      variant: this.data.game.variant.key,
      fen: this.vm.step.fen,
      path: this.vm.pathStr
    });
  }.bind(this));

  var sound = {
    move: throttle(50, false, $.sound.move),
    capture: throttle(50, false, $.sound.capture),
    check: throttle(50, false, $.sound.check)
  };

  this.jump = function(path) {
    this.vm.path = path;
    this.vm.pathStr = treePath.write(path);
    if (window.history.replaceState)
      window.history.replaceState(null, null, '#' + path[0].ply);
    showGround();
    if (!this.vm.step.uci) sound.move(); // initial position
    else if (this.vm.justPlayed !== this.vm.step.uci) {
      if (this.vm.step.san.indexOf('x') !== -1) sound.capture();
      else sound.move();
      this.vm.justPlayed = null;
    }
    if (/\+|\#/.test(this.vm.step.san)) sound.check();
    startCeval();
  }.bind(this);

  this.userJump = function(path) {
    this.autoplay.stop();
    this.jump(path);
  }.bind(this);

  this.jumpToMain = function(ply) {
    this.userJump([{
      ply: ply,
      variation: null
    }]);
  }.bind(this);

  this.jumpToIndex = function(index) {
    this.jumpToMain(index + 1 + this.data.game.startedAtTurn);
  }.bind(this);

  var forsyth = function(role) {
    return role === 'knight' ? 'n' : role[0];
  };

  var userMove = function(orig, dest, capture) {
    this.vm.justPlayed = orig + dest;
    sound[capture ? 'capture' : 'move']();
    if (!promotion.start(this, orig, dest, sendMove)) sendMove(orig, dest);
  }.bind(this);

  var sendMove = function(orig, dest, prom) {
    var move = {
      orig: orig,
      dest: dest,
      variant: this.data.game.variant.key,
      fen: this.vm.step.fen,
      path: this.vm.pathStr
    };
    if (prom) move.promotion = prom;
    this.socket.sendAnaMove(move);
    // prepare premoving
    this.chessground.set({
      turnColor: this.chessground.data.movable.color,
      movable: {
        color: opposite(this.chessground.data.movable.color)
      }
    });
  }.bind(this);

  this.addStep = function(step, path) {
    var newPath = this.analyse.addStep(step, treePath.read(path));
    this.jump(newPath);
    m.redraw();
    this.chessground.playPremove();
  }.bind(this);

  this.addDests = function(dests, path) {
    this.analyse.addDests(dests, treePath.read(path));
    if (path === this.vm.pathStr) showGround();
    this.chessground.playPremove();
  }.bind(this);

  this.reset = function() {
    this.chessground.set(this.vm.situation);
    m.redraw();
  }.bind(this);

  this.encodeStepFen = function() {
    return this.vm.step.fen.replace(/\s/g, '_');
  }.bind(this);

  this.socket = new socket(opts.socketSend, this);

  this.currentAnyEval = function() {
    return this.vm.step ? (this.vm.step.eval || this.vm.step.ceval) : null;
  }.bind(this);

  this.forecast = opts.data.forecast ? forecastCtrl(
    opts.data.forecast,
    router.forecasts(this.data)) : null;

  var allowCeval = (
    util.synthetic(this.data) || !game.playable(this.data)
  ) && ['standard', 'fromPosition', 'chess960'].indexOf(this.data.game.variant.key) !== -1;

  this.ceval = cevalCtrl(allowCeval,
    throttle(300, false, function(res) {
      this.analyse.updateAtPath(res.work.path, function(step) {
        if (step.ceval && step.ceval.depth >= res.eval.depth) return;
        step.ceval = res.eval;
        setAutoShapesFromEval();
        m.redraw();
      });
    }.bind(this)));

  this.canUseCeval = function(step) {
    return step.dests !== '';
  }.bind(this);

  var startCeval = throttle(500, false, function() {
    if (this.ceval.enabled() && this.canUseCeval(this.vm.step))
      this.ceval.start(this.vm.path, this.analyse.getSteps(this.vm.path));
  }.bind(this));

  this.toggleCeval = function() {
    setAutoShapesFromEval();
    this.ceval.toggle();
    startCeval();
  }.bind(this);

  var setAutoShapesFromEval = function() {
    var s = this.vm.step, shapes = [];
    if (s.eval && s.eval.best) shapes.push(makeAutoShapeFromUci(s.eval.best, 'paleGreen'));
    if (s.ceval && s.ceval.best) shapes.push(makeAutoShapeFromUci(s.ceval.best, 'paleBlue'));
    this.chessground.setAutoShapes(shapes);
  }.bind(this);

  var makeAutoShapeFromUci = function(uci, brush) {
    return {
      orig: uci.slice(0, 2),
      dest: uci.slice(2, 4),
      brush: brush
    };
  };

  this.trans = function(key) {
    var str = opts.i18n[key] || key;
    Array.prototype.slice.call(arguments, 1).forEach(function(arg) {
      str = str.replace('%s', arg);
    });
    return str;
  };

  showGround();
  keyboard(this);
  startCeval();
};
<commit_msg>tweak eval arrow system<commit_after>var chessground = require('chessground');
var opposite = chessground.util.opposite;
var data = require('./data');
var analyse = require('./analyse');
var ground = require('./ground');
var keyboard = require('./keyboard');
var treePath = require('./path');
var actionMenu = require('./actionMenu').controller;
var autoplay = require('./autoplay');
var control = require('./control');
var promotion = require('./promotion');
var util = require('./util');
var throttle = require('./util').throttle;
var socket = require('./socket');
var forecastCtrl = require('./forecast/forecastCtrl');
var cevalCtrl = require('./ceval/cevalCtrl');
var router = require('game').router;
var game = require('game').game;
var m = require('mithril');

module.exports = function(opts) {

  this.data = data({}, opts.data);
  this.userId = opts.userId;
  this.ongoing = !util.synthetic(this.data) && game.playable(this.data);

  this.analyse = new analyse(this.data.steps);
  this.actionMenu = new actionMenu();
  this.autoplay = new autoplay(this);

  var initialPath = opts.path ? treePath.read(opts.path) : treePath.default(this.analyse.firstPly());
  if (initialPath[0].ply >= this.data.steps.length)
    initialPath = treePath.default(this.data.steps.length - 1);

  this.vm = {
    path: initialPath,
    pathStr: treePath.write(initialPath),
    initialPathStr: '' + opts.data.path,
    step: null,
    cgConfig: null,
    comments: true,
    flip: false
  };

  this.flip = function() {
    this.vm.flip = !this.vm.flip;
    this.chessground.set({
      orientation: this.vm.flip ? this.data.opponent.color : this.data.player.color
    });
  }.bind(this);

  this.togglePlay = function(delay) {
    this.autoplay.toggle(delay);
    this.actionMenu.open = false;
  }.bind(this);

  var showGround = function() {
    var s;
    try {
      s = this.analyse.getStep(this.vm.path);
    } catch (e) {
      console.log(e);
    }
    if (!s) {
      this.vm.path = treePath.default(this.analyse.firstPly());
      this.vm.pathStr = treePath.write(this.vm.path);
      s = this.analyse.getStep(this.vm.path);
    }
    var color = s.ply % 2 === 0 ? 'white' : 'black';
    var dests = util.readDests(s.dests);
    var config = {
      fen: s.fen,
      turnColor: color,
      movable: {
        color: dests && Object.keys(dests).length > 0 ? color : null,
        dests: dests || {}
      },
      check: s.check,
      lastMove: s.uci ? [s.uci.substr(0, 2), s.uci.substr(2, 2)] : null,
    };
    if (!dests && !s.check) {
      // premove while dests are loading from server
      // can't use when in check because it highlights the wrong king
      config.turnColor = opposite(color);
      config.movable.color = color;
    }
    this.vm.step = s;
    this.vm.cgConfig = config;
    if (!this.chessground)
      this.chessground = ground.make(this.data, config, userMove);
    this.chessground.set(config);
    if (opts.onChange) opts.onChange(config.fen, this.vm.path);
    if (!dests) getDests();
    setAutoShapesFromEval();
  }.bind(this);

  var getDests = throttle(200, false, function() {
    if (this.vm.step.dests) return;
    this.socket.sendAnaDests({
      variant: this.data.game.variant.key,
      fen: this.vm.step.fen,
      path: this.vm.pathStr
    });
  }.bind(this));

  var sound = {
    move: throttle(50, false, $.sound.move),
    capture: throttle(50, false, $.sound.capture),
    check: throttle(50, false, $.sound.check)
  };

  this.jump = function(path) {
    this.vm.path = path;
    this.vm.pathStr = treePath.write(path);
    if (window.history.replaceState)
      window.history.replaceState(null, null, '#' + path[0].ply);
    showGround();
    if (!this.vm.step.uci) sound.move(); // initial position
    else if (this.vm.justPlayed !== this.vm.step.uci) {
      if (this.vm.step.san.indexOf('x') !== -1) sound.capture();
      else sound.move();
      this.vm.justPlayed = null;
    }
    if (/\+|\#/.test(this.vm.step.san)) sound.check();
    startCeval();
  }.bind(this);

  this.userJump = function(path) {
    this.autoplay.stop();
    this.jump(path);
  }.bind(this);

  this.jumpToMain = function(ply) {
    this.userJump([{
      ply: ply,
      variation: null
    }]);
  }.bind(this);

  this.jumpToIndex = function(index) {
    this.jumpToMain(index + 1 + this.data.game.startedAtTurn);
  }.bind(this);

  var forsyth = function(role) {
    return role === 'knight' ? 'n' : role[0];
  };

  var userMove = function(orig, dest, capture) {
    this.vm.justPlayed = orig + dest;
    sound[capture ? 'capture' : 'move']();
    if (!promotion.start(this, orig, dest, sendMove)) sendMove(orig, dest);
  }.bind(this);

  var sendMove = function(orig, dest, prom) {
    var move = {
      orig: orig,
      dest: dest,
      variant: this.data.game.variant.key,
      fen: this.vm.step.fen,
      path: this.vm.pathStr
    };
    if (prom) move.promotion = prom;
    this.socket.sendAnaMove(move);
    // prepare premoving
    this.chessground.set({
      turnColor: this.chessground.data.movable.color,
      movable: {
        color: opposite(this.chessground.data.movable.color)
      }
    });
  }.bind(this);

  this.addStep = function(step, path) {
    var newPath = this.analyse.addStep(step, treePath.read(path));
    this.jump(newPath);
    m.redraw();
    this.chessground.playPremove();
  }.bind(this);

  this.addDests = function(dests, path) {
    this.analyse.addDests(dests, treePath.read(path));
    if (path === this.vm.pathStr) showGround();
    this.chessground.playPremove();
  }.bind(this);

  this.reset = function() {
    this.chessground.set(this.vm.situation);
    m.redraw();
  }.bind(this);

  this.encodeStepFen = function() {
    return this.vm.step.fen.replace(/\s/g, '_');
  }.bind(this);

  this.socket = new socket(opts.socketSend, this);

  this.currentAnyEval = function() {
    return this.vm.step ? (this.vm.step.eval || this.vm.step.ceval) : null;
  }.bind(this);

  this.forecast = opts.data.forecast ? forecastCtrl(
    opts.data.forecast,
    router.forecasts(this.data)) : null;

  var allowCeval = (
    util.synthetic(this.data) || !game.playable(this.data)
  ) && ['standard', 'fromPosition', 'chess960'].indexOf(this.data.game.variant.key) !== -1;

  this.ceval = cevalCtrl(allowCeval,
    throttle(300, false, function(res) {
      this.analyse.updateAtPath(res.work.path, function(step) {
        if (step.ceval && step.ceval.depth >= res.eval.depth) return;
        step.ceval = res.eval;
        setAutoShapesFromEval();
        m.redraw();
      });
    }.bind(this)));

  this.canUseCeval = function(step) {
    return step.dests !== '';
  }.bind(this);

  var startCeval = throttle(500, false, function() {
    if (this.ceval.enabled() && this.canUseCeval(this.vm.step))
      this.ceval.start(this.vm.path, this.analyse.getSteps(this.vm.path));
  }.bind(this));

  this.toggleCeval = function() {
    this.ceval.toggle();
    if (this.ceval.enabled())
      setAutoShapesFromEval();
    else
      this.chessground.setAutoShapes([]);
    startCeval();
  }.bind(this);

  var setAutoShapesFromEval = function() {
    if (!this.ceval.enabled()) return;
    var s = this.vm.step,
      shapes = [];
    if (s.eval && s.eval.best) shapes.push(makeAutoShapeFromUci(s.eval.best, 'paleGreen'));
    if (s.ceval && s.ceval.best) shapes.push(makeAutoShapeFromUci(s.ceval.best, 'paleBlue'));
    this.chessground.setAutoShapes(shapes);
  }.bind(this);

  var makeAutoShapeFromUci = function(uci, brush) {
    return {
      orig: uci.slice(0, 2),
      dest: uci.slice(2, 4),
      brush: brush
    };
  };

  this.trans = function(key) {
    var str = opts.i18n[key] || key;
    Array.prototype.slice.call(arguments, 1).forEach(function(arg) {
      str = str.replace('%s', arg);
    });
    return str;
  };

  showGround();
  keyboard(this);
  startCeval();
};
<|endoftext|>


<commit_before>/**
 * @woltlabExcludeBundle tiny
 */
define(["require", "exports", "tslib", "../../Core", "../../Dom/Util", "../../Language", "../Dialog"], function (require, exports, tslib_1, Core_1, Util_1, Language, Dialog_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.showDialog = void 0;
    Util_1 = tslib_1.__importDefault(Util_1);
    Language = tslib_1.__importStar(Language);
    Dialog_1 = tslib_1.__importDefault(Dialog_1);
    class UiRedactorLink {
        boundListener = false;
        submitCallback;
        open(options) {
            Dialog_1.default.open(this);
            Dialog_1.default.setTitle(this, Language.get("wcf.editor.link." + (options.insert ? "add" : "edit")));
            const submitButton = document.getElementById("redactor-modal-button-action");
            submitButton.textContent = Language.get("wcf.global.button." + (options.insert ? "insert" : "save"));
            this.closeCallback = options.closeCallback;
            this.submitCallback = options.submitCallback;
            // Redactor might modify the button, thus we cannot bind it in the dialog's `onSetup()` callback.
            if (!this.boundListener) {
                this.boundListener = true;
                submitButton.addEventListener("click", () => this.submit());
            }
        }
        submit() {
            let returnValue;
            (0, Core_1.interactWithRedactor)(() => {
                returnValue = this.submitCallback();
            });
            if (returnValue) {
                Dialog_1.default.close(this);
            }
            else {
                const url = document.getElementById("redactor-link-url");
                const errorMessage = url.value.trim() === "" ? "wcf.global.form.error.empty" : "wcf.editor.link.error.invalid";
                Util_1.default.innerError(url, Language.get(errorMessage));
            }
        }
        _dialogSetup() {
            return {
                id: "redactorDialogLink",
                options: {
                    onClose: () => {
                        const url = document.getElementById("redactor-link-url");
                        const small = url.nextElementSibling;
                        if (small && small.nodeName === "SMALL") {
                            small.remove();
                        }
                        this.closeCallback();
                    },
                    onSetup: (content) => {
                        const submitButton = content.querySelector(".formSubmit > .buttonPrimary");
                        if (submitButton !== null) {
                            content.querySelectorAll('input[type="url"], input[type="text"]').forEach((input) => {
                                input.addEventListener("keyup", (event) => {
                                    if (event.key === "Enter") {
                                        submitButton.click();
                                    }
                                });
                            });
                        }
                    },
                },
                source: `

            ${Language.get("wcf.editor.link.url")}

            <input type="url" id="redactor-link-url" class="long">

            ${Language.get("wcf.editor.link.text")}

            <input type="text" id="redactor-link-url-text" class="long">

          <button type="button" id="redactor-modal-button-action" class="button buttonPrimary"></button>

`,
            };
        }
    }
    let uiRedactorLink;
    function showDialog(options) {
        if (!uiRedactorLink) {
            uiRedactorLink = new UiRedactorLink();
        }
        uiRedactorLink.open(options);
    }
    exports.showDialog = showDialog;
});
<commit_msg>Rebuild compiled JavaScript<commit_after>/**
 * @woltlabExcludeBundle tiny
 */
define(["require", "exports", "tslib", "../../Core", "../../Dom/Util", "../../Language", "../Dialog"], function (require, exports, tslib_1, Core_1, Util_1, Language, Dialog_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.showDialog = void 0;
    Util_1 = tslib_1.__importDefault(Util_1);
    Language = tslib_1.__importStar(Language);
    Dialog_1 = tslib_1.__importDefault(Dialog_1);
    class UiRedactorLink {
        boundListener = false;
        closeCallback;
        submitCallback;
        open(options) {
            Dialog_1.default.open(this);
            Dialog_1.default.setTitle(this, Language.get("wcf.editor.link." + (options.insert ? "add" : "edit")));
            const submitButton = document.getElementById("redactor-modal-button-action");
            submitButton.textContent = Language.get("wcf.global.button." + (options.insert ? "insert" : "save"));
            this.closeCallback = options.closeCallback;
            this.submitCallback = options.submitCallback;
            // Redactor might modify the button, thus we cannot bind it in the dialog's `onSetup()` callback.
            if (!this.boundListener) {
                this.boundListener = true;
                submitButton.addEventListener("click", () => this.submit());
            }
        }
        submit() {
            let returnValue;
            (0, Core_1.interactWithRedactor)(() => {
                returnValue = this.submitCallback();
            });
            if (returnValue) {
                Dialog_1.default.close(this);
            }
            else {
                const url = document.getElementById("redactor-link-url");
                const errorMessage = url.value.trim() === "" ? "wcf.global.form.error.empty" : "wcf.editor.link.error.invalid";
                Util_1.default.innerError(url, Language.get(errorMessage));
            }
        }
        _dialogSetup() {
            return {
                id: "redactorDialogLink",
                options: {
                    onClose: () => {
                        const url = document.getElementById("redactor-link-url");
                        const small = url.nextElementSibling;
                        if (small && small.nodeName === "SMALL") {
                            small.remove();
                        }
                        this.closeCallback();
                    },
                    onSetup: (content) => {
                        const submitButton = content.querySelector(".formSubmit > .buttonPrimary");
                        if (submitButton !== null) {
                            content.querySelectorAll('input[type="url"], input[type="text"]').forEach((input) => {
                                input.addEventListener("keyup", (event) => {
                                    if (event.key === "Enter") {
                                        submitButton.click();
                                    }
                                });
                            });
                        }
                    },
                },
                source: `

            ${Language.get("wcf.editor.link.url")}

            <input type="url" id="redactor-link-url" class="long">

            ${Language.get("wcf.editor.link.text")}

            <input type="text" id="redactor-link-url-text" class="long">

          <button type="button" id="redactor-modal-button-action" class="button buttonPrimary"></button>

`,
            };
        }
    }
    let uiRedactorLink;
    function showDialog(options) {
        if (!uiRedactorLink) {
            uiRedactorLink = new UiRedactorLink();
        }
        uiRedactorLink.open(options);
    }
    exports.showDialog = showDialog;
});
<|endoftext|>