<commit_before>/* global app, _ */

// callback from twitter to embed tweet html
window.addTweet = function (data) {
	var id = data.url.substr(data.url.lastIndexOf('/') + 1);
	var element = $('.tweet_' + id);
	element.empty();
	element.append(data.html);
};

app.filter('trusted', ['$sce', function ($sce) {
	return function (url) {
		return $sce.trustAsResourceUrl(url);
	};
}]);

var youtubeRegexp = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;

app.directive('bunkerMessage', function ($compile, emoticons, bunkerData, bunkerConstants, $timeout) {

	function replaceAll(str, find, replace) {
		return str.split(find).join(replace);
	}

	return {
		template: '',
		scope: {
			bunkerMessage: '=',
			media: '@',
			watch: '@'
		},
		link: function (scope, elem) {

			// since we are passing in a bunker message OR room, run the watch on the room topic
			var shouldWatch = typeof scope.watch !== 'undefined' ? scope.$eval(scope.watch) : true;
			var textListener = scope.$watch('bunkerMessage.text', textWatch);
			var topicListener = scope.$watch('bunkerMessage.topic', textWatch);

			function textWatch(text) {
				if (!text) return;

				// Parse quotes
				if (scope.bunkerMessage.type == 'code') {
					text = parseCode(text);
				}
				else if (scope.bunkerMessage.type == 'hangman') {
					text = parseHangman(text);
				}
				else if (text.match(/
/g)) {
					text = createQuotedBlock(text);
				}
				else {
					text = parseFormatting(text);
					if (bunkerData.userSettings.showEmoticons) {
						text = parseEmoticons(text);
					}
					text = parseMedia(text);
				}

				scope.formatted = text;

				// After 60 seconds the message is not editable anymore so we can kill the watch on its text
				var millisecondsSinceCreated = moment().diff(scope.bunkerMessage.createdAt);
				if (!shouldWatch || millisecondsSinceCreated > bunkerConstants.editWindowMilliseconds) {
					// We can kill the watch on text, this message is now static
					textListener();
				}
				else {
					// kill this watch once the window passes
					$timeout(textListener, bunkerConstants.editWindowMilliseconds - millisecondsSinceCreated);
				}

				// Most messages are not a topic - at this point we can test this and kill the watch on that if necessary
				if (!shouldWatch || !scope.bunkerMessage.topic) {
					topicListener();
				}
			}

			function createQuotedBlock(text) {
				// Scan for overtabs
				var lines = text.split('
');
				var firstLineSpacingMatch = _.first(lines).match(/^((	)*)/);

				// If we have some spacing on the first line, remove the same spacing from all other lines (detabs everything)
				if (firstLineSpacingMatch) {
					var firstLineSpacingExpression = new RegExp('^' + firstLineSpacingMatch[1] + '');
					var spacingRemoved = _.map(lines, function (line) {
						return line.replace(firstLineSpacingExpression, '');
					});
					text = spacingRemoved.join('
');
				}

				var attachedMedia = angular.element('

' + text + '

');

				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());

				return '';
			}

			function parseHangman(text){
				return text.replace(/:hangman(\d):/, '');
			}

			function parseCode(text) {
				var attachedMedia = angular.element('

' + text + '

');
				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());
				return '';
			}

			function parseEmoticons(text) {
				var replacedEmotes = {};

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return known.replace(/\.\w{1,4}$/, '').toLowerCase() == emoticonText.replace(/:/g, '').toLowerCase();
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						text = replaceAll(text, emoticonText,
							'');
						replacedEmotes[knownEmoticon] = true;
					}
				});
				return text;
			}

			function parseFormatting(text) {

				var types = [
					{marker: '*', tag: 'strong'},
					{marker: '_', tag: 'em'},
					{marker: '~', tag: 'del'},
					{marker: '|', tag: 'mark'}
				];

				_.each(types, function (type) {
					var lookup = new RegExp('(?:[^A-z0-9]|^)(\\' + type.marker + '[^\\' + type.marker + ']+\\' + type.marker + ')(?:[^A-z0-9]|$)', 'g');

					var match;
					while ((match = lookup.exec(text)) !== null) {
						text = replaceAll(text, match[0].trim(), '<' + type.tag + '>' + replaceAll(match[0], type.marker, '') + '</' + type.tag + '>');
					}
				});

				return text;
			}

			function parseMedia(text) {
				var shouldParseMedia = typeof scope.media !== 'undefined' ? scope.$eval(scope.media) : true;
				var replacedLinks = {};

				// Parse links
				var attachedMedia;
				_.each(text.match(/https?:\/\/\S+/gi), function (link) {

					// Only parse media (images, youtube) if asked to
					if (shouldParseMedia) {
						if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedMedia) {
							// Image link
							attachedMedia = angular.element('

');
						}
						else if (/imgur.com\/\w*\.(gifv|webm|mp4)$/i.test(link) && !attachedMedia) {
							var imgurLinkMpeg = link.replace('webm', 'mp4').replace('gifv', 'mp4');
							var imgurLinkWebm = link.replace('mp4', 'webm').replace('gifv', 'webm');
							attachedMedia = angular.element('' +
								'
<video class="imgur-gifv" preload="auto" autoplay muted webkit-playsinline loop><source type="video/webm" src="' + imgurLinkWebm + '"><source type="video/mp4" src="' + imgurLinkMpeg + '"></video>' +
								'
');
						}
						else if (/\.(gifv|mp4|webm)$/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
								'
' +
								'<video autoplay loop muted><source type="video/mp4" src="' + link.toLowerCase().replace('gifv', 'mp4') + '"></video>' +
								'
');
						}
						else if (youtubeRegexp.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
								'
' +
								'<youtube-video video-url="\'' + link + '\'"></youtube-video>' +
								'
');
						}
						else if (/(www\.)?(twitter\.com\/)/i.test(link) && !attachedMedia) {
							var id = link.substr(link.lastIndexOf('/') + 1);
							if (id) { /* don't embed tweet if we can't get the id from the link */
								attachedMedia = angular.element('' +
									'
' +
									'
' +
									'

');
							}
						}
						else if (/vimeo\.com(?:.*)?\/([A-z0-9]*)$/i.test(link) && !attachedMedia) {
							var match = /vimeo\.com(?:.*)?\/([a-zA-Z0-9]*)$/i.exec(link);
							attachedMedia = angular.element('' +
								'
' +
								'' +
								'
');
						}
					}

					if (!replacedLinks[link]) {
						text = replaceAll(text, link, '' + link + '');
						replacedLinks[link] = true;
					}
				});

				// If we made an image, attach it now
				if (attachedMedia) {
					angular.element(elem).append(attachedMedia);
					$compile(attachedMedia)(scope.$new());
				}

				return text;
			}
		}
	};
});
<commit_msg>code cleanup<commit_after>/* global app, _ */

// callback from twitter to embed tweet html
window.addTweet = function (data) {
	var id = data.url.substr(data.url.lastIndexOf('/') + 1);
	var element = $('.tweet_' + id);
	element.empty();
	element.append(data.html);
};

app.filter('trusted', ['$sce', function ($sce) {
	return function (url) {
		return $sce.trustAsResourceUrl(url);
	};
}]);

var youtubeRegexp = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;

app.directive('bunkerMessage', function ($compile, emoticons, bunkerData, bunkerConstants, $timeout) {

	function replaceAll(str, find, replace) {
		return str.split(find).join(replace);
	}

	return {
		template: '',
		scope: {
			bunkerMessage: '=',
			media: '@',
			watch: '@'
		},
		link: function (scope, elem) {

			// since we are passing in a bunker message OR room, run the watch on the room topic
			var shouldWatch = typeof scope.watch !== 'undefined' ? scope.$eval(scope.watch) : true;
			var textListener = scope.$watch('bunkerMessage.text', textWatch);
			var topicListener = scope.$watch('bunkerMessage.topic', textWatch);

			function textWatch(text) {
				if (!text) return;

				if (scope.bunkerMessage.type == 'code') {
					text = parseCode(text);
				}
				else if (scope.bunkerMessage.type == 'hangman') {
					text = parseHangman(text);
				}
				else if (text.match(/
/g)) {  // unicode 10 is tabs/whitespace
					text = createQuotedBlock(text);
				}
				else {
					text = parseFormatting(text);
					if (bunkerData.userSettings.showEmoticons) {
						text = parseEmoticons(text);
					}
					text = parseMedia(text);
				}

				scope.formatted = text;

				// After 60 seconds the message is not editable anymore so we can kill the watch on its text
				var millisecondsSinceCreated = moment().diff(scope.bunkerMessage.createdAt);
				if (!shouldWatch || millisecondsSinceCreated > bunkerConstants.editWindowMilliseconds) {
					// We can kill the watch on text, this message is now static
					textListener();
				}
				else {
					// kill this watch once the window passes
					$timeout(textListener, bunkerConstants.editWindowMilliseconds - millisecondsSinceCreated);
				}

				// Most messages are not a topic - at this point we can test this and kill the watch on that if necessary
				if (!shouldWatch || !scope.bunkerMessage.topic) {
					topicListener();
				}
			}

			function createQuotedBlock(text) {
				// Scan for overtabs
				var lines = text.split('
');
				var firstLineSpacingMatch = _.first(lines).match(/^((	)*)/);

				// If we have some spacing on the first line, remove the same spacing from all other lines (detabs everything)
				if (firstLineSpacingMatch) {
					var firstLineSpacingExpression = new RegExp('^' + firstLineSpacingMatch[1] + '');
					var spacingRemoved = _.map(lines, function (line) {
						return line.replace(firstLineSpacingExpression, '');
					});
					text = spacingRemoved.join('
');
				}

				var attachedMedia = angular.element('

' + text + '

');

				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());

				return '';
			}

			function parseHangman(text) {
				return text.replace(/:hangman(\d):/, '');
			}

			function parseCode(text) {
				var attachedMedia = angular.element('

' + text + '

');
				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());
				return '';
			}

			function parseEmoticons(text) {
				var replacedEmotes = {};

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return known.replace(/\.\w{1,4}$/, '').toLowerCase() == emoticonText.replace(/:/g, '').toLowerCase();
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						text = replaceAll(text, emoticonText,
							'');
						replacedEmotes[knownEmoticon] = true;
					}
				});
				return text;
			}

			function parseFormatting(text) {

				var types = [
					{marker: '*', tag: 'strong'},
					{marker: '_', tag: 'em'},
					{marker: '~', tag: 'del'},
					{marker: '|', tag: 'mark'}
				];

				_.each(types, function (type) {
					var lookup = new RegExp('(?:[^A-z0-9]|^)(\\' + type.marker + '[^\\' + type.marker + ']+\\' + type.marker + ')(?:[^A-z0-9]|$)', 'g');

					var match;
					while ((match = lookup.exec(text)) !== null) {
						text = replaceAll(text, match[0].trim(), '<' + type.tag + '>' + replaceAll(match[0], type.marker, '') + '</' + type.tag + '>');
					}
				});

				return text;
			}

			function parseMedia(text) {
				var shouldParseMedia = typeof scope.media !== 'undefined' ? scope.$eval(scope.media) : true;
				var replacedLinks = {};

				// Parse links
				var attachedMedia;
				_.each(text.match(/https?:\/\/\S+/gi), function (link) {

					// Only parse media (images, youtube) if asked to
					if (shouldParseMedia) {
						if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedMedia) {
							// Image link
							attachedMedia = angular.element('

');
						}
						else if (/imgur.com\/\w*\.(gifv|webm|mp4)$/i.test(link) && !attachedMedia) {
							var imgurLinkMpeg = link.replace('webm', 'mp4').replace('gifv', 'mp4');
							var imgurLinkWebm = link.replace('mp4', 'webm').replace('gifv', 'webm');
							attachedMedia = angular.element('' +
								'
<video class="imgur-gifv" preload="auto" autoplay muted webkit-playsinline loop><source type="video/webm" src="' + imgurLinkWebm + '"><source type="video/mp4" src="' + imgurLinkMpeg + '"></video>' +
								'
');
						}
						else if (/\.(gifv|mp4|webm)$/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
								'
' +
								'<video autoplay loop muted><source type="video/mp4" src="' + link.toLowerCase().replace('gifv', 'mp4') + '"></video>' +
								'
');
						}
						else if (youtubeRegexp.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
								'
' +
								'<youtube-video video-url="\'' + link + '\'"></youtube-video>' +
								'
');
						}
						else if (/(www\.)?(twitter\.com\/)/i.test(link) && !attachedMedia) {
							var id = link.substr(link.lastIndexOf('/') + 1);
							if (id) { /* don't embed tweet if we can't get the id from the link */
								attachedMedia = angular.element('' +
									'
' +
									'
' +
									'

');
							}
						}
						else if (/vimeo\.com(?:.*)?\/([A-z0-9]*)$/i.test(link) && !attachedMedia) {
							var match = /vimeo\.com(?:.*)?\/([a-zA-Z0-9]*)$/i.exec(link);
							attachedMedia = angular.element('' +
								'
' +
								'' +
								'
');
						}
					}

					if (!replacedLinks[link]) {
						text = replaceAll(text, link, '' + link + '');
						replacedLinks[link] = true;
					}
				});

				// If we made an image, attach it now
				if (attachedMedia) {
					angular.element(elem).append(attachedMedia);
					$compile(attachedMedia)(scope.$new());
				}

				return text;
			}
		}
	};
});
<|endoftext|>


<commit_before>var app = require('http').createServer(handler);
var LISTENING_PORT = process.env.PORT || 9000;
var STATUS_CODE = 200;
var sleep = require('sleep');
var SECONDS_TO_SLEEP = 0;

app.listen(LISTENING_PORT);

function handler (req, res) {
  if (req.method == "POST") {
    res.writeHead(STATUS_CODE, {'Content-Type': 'application/json'});

    var data = '';
    req.on('data', function(chunk) {
      data += chunk;
    });

    req.on('end', function() {
      console.log('Logging POST request:');

      console.log('Headers:');
      console.log(req.headers);

      console.log('Body:');
      console.log(data.toString());
      console.log();
    });
  }

  if (req.method == "GET") {
    res.writeHead(STATUS_CODE, {'Content-Type': 'text/html'});

    res.write("<title>Polis.js</title>
Polis.js

Running!
");

    req.on('end', function() {
      console.log('Logging GET request:');

      console.log('Headers:');
      console.log(req.headers);
      console.log();
    });
  }

  sleep.sleep(SECONDS_TO_SLEEP);
  res.end();
}

console.log("Listening to port " + LISTENING_PORT);
console.log("Returning status code " + STATUS_CODE);
console.log();
<commit_msg>Create handlers for GET and POST verbs<commit_after>var app = require('http').createServer(handler);
var LISTENING_PORT = process.env.PORT || 9000;
var STATUS_CODE = 200;
var sleep = require('sleep');
var SECONDS_TO_SLEEP = 0;

app.listen(LISTENING_PORT);

handlers = {"POST": PostHandler, "GET": GetHandler};

function handler (req, res) {
  var handler = new handlers[req.method];

  handler.handle(req, res);

  sleep.sleep(SECONDS_TO_SLEEP);
  res.end();
}

function PostHandler() { }

PostHandler.prototype.handle = function(req, res) {
  res.writeHead(STATUS_CODE, {'Content-Type': 'application/json'});

  var data = '';
  req.on('data', function(chunk) {
    data += chunk;
  });

  req.on('end', function() {
    console.log('Logging POST request:');

    console.log('Headers:');
    console.log(req.headers);

    console.log('Body:');
    console.log(data.toString());
    console.log();
  });
}

function GetHandler() { }

GetHandler.prototype.handle = function(req, res) {
  res.writeHead(STATUS_CODE, {'Content-Type': 'text/html'});

  res.write("<title>Polis.js</title>
Polis.js

Running!
");

  req.on('end', function() {
    console.log('Logging GET request:');

    console.log('Headers:');
    console.log(req.headers);
    console.log();
  });
}

console.log("Listening to port " + LISTENING_PORT);
console.log("Returning status code " + STATUS_CODE);
console.log();
<|endoftext|>


<commit_before>/* global app, _ */

// callback from twitter to embed tweet html
window.addTweet = function (data) {
	var id = data.url.substr(data.url.lastIndexOf('/') + 1);
	var element = $('.tweet_' + id);
	element.empty();
	element.append(data.html);
};

app.filter('trusted', ['$sce', function ($sce) {
	return function (url) {
		return $sce.trustAsResourceUrl(url);
	};
}]);

app.directive('bunkerMessage', function ($compile, emoticons, bunkerData, bunkerConstants, $timeout) {

	function replaceAll(str, find, replace) {
		return str.split(find).join(replace);
	}

	return {
		template: '',
		scope: {
			bunkerMessage: '=',
			media: '@',
			watch: '@'
		},
		link: function (scope, elem) {

			// since we are passing in a bunker message OR room, run the watch on the room topic
			var shouldWatch = typeof scope.watch !== 'undefined' ? scope.$eval(scope.watch) : true;
			var textListener = scope.$watch('bunkerMessage.text', textWatch);
			var topicListener = scope.$watch('bunkerMessage.topic', textWatch);

			function textWatch(text) {
				if (!text) return;

				// Parse quotes
				if (text.match(/
/g)) {
					text = createQuotedBlock(text);
				}
				else {
					text = parseFormatting(text);
					if (bunkerData.userSettings.showEmoticons) {
						text = parseEmoticons(text);
					}
					text = parseMedia(text);
				}

				scope.formatted = text;

				// After 60 seconds the message is not editable anymore so we can kill the watch on its text
				var millisecondsSinceCreated = moment().diff(scope.bunkerMessage.createdAt);
				if (!shouldWatch || millisecondsSinceCreated > bunkerConstants.editWindowMilliseconds) {
					// We can kill the watch on text, this message is now static
					textListener();
				}
				else {
					// kill this watch once the window passes
					$timeout(textListener, bunkerConstants.editWindowMilliseconds - millisecondsSinceCreated);
				}

				// Most messages are not a topic - at this point we can test this and kill the watch on that if necessary
				if (!shouldWatch || !scope.bunkerMessage.topic) {
					topicListener();
				}
			}

			function createQuotedBlock(text) {
				// Scan for overtabs
				var lines = text.split('
');
				var firstLineSpacingMatch = _.first(lines).match(/^((	)*)/);

				// If we have some spacing on the first line, remove the same spacing from all other lines (detabs everything)
				if (firstLineSpacingMatch) {
					var firstLineSpacingExpression = new RegExp('^' + firstLineSpacingMatch[1] + '');
					var spacingRemoved = _.map(lines, function (line) {
						return line.replace(firstLineSpacingExpression, '');
					});
					text = spacingRemoved.join('
');
				}

				var attachedMedia = angular.element('

' + text + '

');
				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());

				return '';
			}

			function parseEmoticons(text) {
				var replacedEmotes = {};

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return known.replace(/\.\w{1,4}$/, '').toLowerCase() == emoticonText.replace(/:/g, '').toLowerCase();
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						text = replaceAll(text, emoticonText,
							'');
						replacedEmotes[knownEmoticon] = true;
					}
				});
				return text;
			}

			function parseFormatting(text) {

				var types = [
					{marker: '*', tag: 'strong'},
					{marker: '_', tag: 'em'},
					{marker: '~', tag: 'del'},
					{marker: '|', tag: 'mark'}
				];

				_.each(types, function (type) {
					var lookup = new RegExp('(?:[^A-z0-9]|^)(\\' + type.marker + '[^\\' + type.marker + ']+\\' + type.marker + ')(?:[^A-z0-9]|$)', 'g');

					var match;
					while ((match = lookup.exec(text)) !== null) {
						text = replaceAll(text, match[0].trim(), '<' + type.tag + '>' + replaceAll(match[0], type.marker, '') + '</' + type.tag + '>');
					}
				});

				return text;
			}

			function parseMedia(text) {
				var shouldParseMedia = typeof scope.media !== 'undefined' ? scope.$eval(scope.media) : true;
				var replacedLinks = {};

				// Parse links
				var attachedMedia;
				_.each(text.match(/https?:\/\/\S+/gi), function (link) {

					// Only parse media (images, youtube) if asked to
					if (shouldParseMedia) {
						if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedMedia) {
							// Image link
							attachedMedia = angular.element('

');
						}
						else if (/imgur.com\/\w*\.(gifv|webm|mp4)$/i.test(link) && !attachedMedia) {
							var imgurLinkMpeg = link.replace('webm', 'mp4').replace('gifv', 'mp4');
							var imgurLinkWebm = link.replace('mp4', 'webm').replace('gifv', 'webm');
							attachedMedia = angular.element('' +
							'
<video class="imgur-gifv" preload="auto" autoplay muted webkit-playsinline loop><source type="video/webm" src="' + imgurLinkWebm + '"><source type="video/mp4" src="' + imgurLinkMpeg + '"></video>' +
							'
');
						}
						else if (/\.(gifv|mp4|webm)$/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
							'
' +
							'<video autoplay loop muted><source type="video/mp4" src="' + link.toLowerCase().replace('gifv', 'mp4') + '"></video>' +
							'
');
						}
						else if (/(www\.)?(youtube\.com|youtu\.?be)\/watch/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
							'
' +
							'<youtube-video video-url="\'' + link + '\'"></youtube-video>' +
							'
');
						}
						else if (/(www\.)?(twitter\.com\/)/i.test(link) && !attachedMedia) {
							var id = link.substr(link.lastIndexOf('/') + 1);
							if (id) { /* don't embed tweet if we can't get the id from the link */
								attachedMedia = angular.element('' +
								'
' +
								'
' +
								'

');
							}
						}
						else if (/(www\.)?(soundcloud\.com\/[a-zA-Z0-9])/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
							'
' +
							'
' +
							'' +
							'

');
						}
						else if (/vimeo\.com(?:.*)?\/([A-z0-9]*)$/i.test(link) && !attachedMedia) {
							var match = /vimeo\.com(?:.*)?\/([a-zA-Z0-9]*)$/i.exec(link);
							attachedMedia = angular.element('' +
							'
' +
							'' +
							'
');
						}
					}

					if (!replacedLinks[link]) {
						text = replaceAll(text, link, '' + link + '');
						replacedLinks[link] = true;
					}
				});

				// If we made an image, attach it now
				if (attachedMedia) {
					angular.element(elem).append(attachedMedia);
					$compile(attachedMedia)(scope.$new());
				}

				return text;
			}
		}
	};
});
<commit_msg>removed soundcloud embed<commit_after>/* global app, _ */

// callback from twitter to embed tweet html
window.addTweet = function (data) {
	var id = data.url.substr(data.url.lastIndexOf('/') + 1);
	var element = $('.tweet_' + id);
	element.empty();
	element.append(data.html);
};

app.filter('trusted', ['$sce', function ($sce) {
	return function (url) {
		return $sce.trustAsResourceUrl(url);
	};
}]);

app.directive('bunkerMessage', function ($compile, emoticons, bunkerData, bunkerConstants, $timeout) {

	function replaceAll(str, find, replace) {
		return str.split(find).join(replace);
	}

	return {
		template: '',
		scope: {
			bunkerMessage: '=',
			media: '@',
			watch: '@'
		},
		link: function (scope, elem) {

			// since we are passing in a bunker message OR room, run the watch on the room topic
			var shouldWatch = typeof scope.watch !== 'undefined' ? scope.$eval(scope.watch) : true;
			var textListener = scope.$watch('bunkerMessage.text', textWatch);
			var topicListener = scope.$watch('bunkerMessage.topic', textWatch);

			function textWatch(text) {
				if (!text) return;

				// Parse quotes
				if (text.match(/
/g)) {
					text = createQuotedBlock(text);
				}
				else {
					text = parseFormatting(text);
					if (bunkerData.userSettings.showEmoticons) {
						text = parseEmoticons(text);
					}
					text = parseMedia(text);
				}

				scope.formatted = text;

				// After 60 seconds the message is not editable anymore so we can kill the watch on its text
				var millisecondsSinceCreated = moment().diff(scope.bunkerMessage.createdAt);
				if (!shouldWatch || millisecondsSinceCreated > bunkerConstants.editWindowMilliseconds) {
					// We can kill the watch on text, this message is now static
					textListener();
				}
				else {
					// kill this watch once the window passes
					$timeout(textListener, bunkerConstants.editWindowMilliseconds - millisecondsSinceCreated);
				}

				// Most messages are not a topic - at this point we can test this and kill the watch on that if necessary
				if (!shouldWatch || !scope.bunkerMessage.topic) {
					topicListener();
				}
			}

			function createQuotedBlock(text) {
				// Scan for overtabs
				var lines = text.split('
');
				var firstLineSpacingMatch = _.first(lines).match(/^((	)*)/);

				// If we have some spacing on the first line, remove the same spacing from all other lines (detabs everything)
				if (firstLineSpacingMatch) {
					var firstLineSpacingExpression = new RegExp('^' + firstLineSpacingMatch[1] + '');
					var spacingRemoved = _.map(lines, function (line) {
						return line.replace(firstLineSpacingExpression, '');
					});
					text = spacingRemoved.join('
');
				}

				var attachedMedia = angular.element('

' + text + '

');
				angular.element(elem).append(attachedMedia);
				$compile(attachedMedia)(scope.$new());

				return '';
			}

			function parseEmoticons(text) {
				var replacedEmotes = {};

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return known.replace(/\.\w{1,4}$/, '').toLowerCase() == emoticonText.replace(/:/g, '').toLowerCase();
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						text = replaceAll(text, emoticonText,
							'');
						replacedEmotes[knownEmoticon] = true;
					}
				});
				return text;
			}

			function parseFormatting(text) {

				var types = [
					{marker: '*', tag: 'strong'},
					{marker: '_', tag: 'em'},
					{marker: '~', tag: 'del'},
					{marker: '|', tag: 'mark'}
				];

				_.each(types, function (type) {
					var lookup = new RegExp('(?:[^A-z0-9]|^)(\\' + type.marker + '[^\\' + type.marker + ']+\\' + type.marker + ')(?:[^A-z0-9]|$)', 'g');

					var match;
					while ((match = lookup.exec(text)) !== null) {
						text = replaceAll(text, match[0].trim(), '<' + type.tag + '>' + replaceAll(match[0], type.marker, '') + '</' + type.tag + '>');
					}
				});

				return text;
			}

			function parseMedia(text) {
				var shouldParseMedia = typeof scope.media !== 'undefined' ? scope.$eval(scope.media) : true;
				var replacedLinks = {};

				// Parse links
				var attachedMedia;
				_.each(text.match(/https?:\/\/\S+/gi), function (link) {

					// Only parse media (images, youtube) if asked to
					if (shouldParseMedia) {
						if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedMedia) {
							// Image link
							attachedMedia = angular.element('

');
						}
						else if (/imgur.com\/\w*\.(gifv|webm|mp4)$/i.test(link) && !attachedMedia) {
							var imgurLinkMpeg = link.replace('webm', 'mp4').replace('gifv', 'mp4');
							var imgurLinkWebm = link.replace('mp4', 'webm').replace('gifv', 'webm');
							attachedMedia = angular.element('' +
							'
<video class="imgur-gifv" preload="auto" autoplay muted webkit-playsinline loop><source type="video/webm" src="' + imgurLinkWebm + '"><source type="video/mp4" src="' + imgurLinkMpeg + '"></video>' +
							'
');
						}
						else if (/\.(gifv|mp4|webm)$/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
							'
' +
							'<video autoplay loop muted><source type="video/mp4" src="' + link.toLowerCase().replace('gifv', 'mp4') + '"></video>' +
							'
');
						}
						else if (/(www\.)?(youtube\.com|youtu\.?be)\/watch/i.test(link) && !attachedMedia) {
							attachedMedia = angular.element('' +
							'
' +
							'<youtube-video video-url="\'' + link + '\'"></youtube-video>' +
							'
');
						}
						else if (/(www\.)?(twitter\.com\/)/i.test(link) && !attachedMedia) {
							var id = link.substr(link.lastIndexOf('/') + 1);
							if (id) { /* don't embed tweet if we can't get the id from the link */
								attachedMedia = angular.element('' +
								'
' +
								'
' +
								'

');
							}
						}
						else if (/vimeo\.com(?:.*)?\/([A-z0-9]*)$/i.test(link) && !attachedMedia) {
							var match = /vimeo\.com(?:.*)?\/([a-zA-Z0-9]*)$/i.exec(link);
							attachedMedia = angular.element('' +
							'
' +
							'' +
							'
');
						}
					}

					if (!replacedLinks[link]) {
						text = replaceAll(text, link, '' + link + '');
						replacedLinks[link] = true;
					}
				});

				// If we made an image, attach it now
				if (attachedMedia) {
					angular.element(elem).append(attachedMedia);
					$compile(attachedMedia)(scope.$new());
				}

				return text;
			}
		}
	};
});
<|endoftext|>


<commit_before>// Cached Globals and Aliases
var _tabs = [];
var _elem = document.all;
var _asyncLoadState = 0;
var _active = -1;
var _previousTabId = -1;
// info on currentTab
var _currentTab = null;
var _opts = {
  // Hide private navigation tabs form the results
  hideIncognito: true
};

// Activate focus on popup opening
_elem.search.focus();

function tryLoadTabs() {
  if (_asyncLoadState === 1) {
    chrome.tabs.query({}, loadTabs);
    _asyncLoadState = 0;
  } else {
    _asyncLoadState++;
  }
}

function setCurrent(tabs) {
  _currentTab = tabs[0];
  tryLoadTabs();
}

function setPrevious(tabId) {
  _previousTabId = tabId;
  tryLoadTabs();
}

function loadTabs(tabs) {
  _tabs = tabs.filter(tabsFilter);
  _tabs.sort(tabsSort);
  _tabs.forEach(genTab);
}

function tabsFilter(tab) {
  if (tab.id === _currentTab.id) { return false; }
  if (typeof tab.id === 'undefined') { return false; }
  return !(_opts.hideIncognito && tab.incognito);
}

function tabsSort(a, b) {
  if (a.id === _previousTabId) { return -1; }
  if (b.id === _previousTabId) { return 1; }
  if (a.windowId !== b.windowId) {
    if (a.windowId === _currentTab.windowId) {
      return -1;
    }
    if (b.windowId === _currentTab.windowId) {
      return 1;
    }
    return a.windowId - b.windowId;
  }
  return a.index - b.index;
}

// generate and append tab button
function genTab(tab, idx) {
  var title = document.createElement('h3');
  title.innerHTML = tab.title;

  var url = document.createElement('span');
  url.innerHTML = tab.url;

  var favIcon = document.createElement('div');
  favIcon.className = 'fav-icon';
  if (tab.windowId === _currentTab.windowId) {
    favIcon.className += ' current';
  }
  favIcon.style.backgroundImage = "url('" + tab.favIconUrl + "')";

  var button = document.createElement('button');
  button.id = 'tab-' + idx;
  button.dataset.id = tab.id;
  button.dataset.index = tab.index;
  button.appendChild(favIcon);
  button.appendChild(title);
  button.appendChild(url);
  _elem.list.appendChild(button);
  tab.buttonHTML = button;
}

function init() {
  var queryOptions = {
    'currentWindow': true,
    'active': true
  };
  chrome.tabs.query(queryOptions, setCurrent);

  //get previous tab from tabHistory
  chrome.runtime.sendMessage({}, setPrevious);
}

// Scroll to element if necessary
function scrollTo(elem) {
  var l = _elem.list;
  var min = l.scrollTop
  var max = l.clientHeight + min;
  var offset = elem.offsetTop;
  var height = elem.offsetHeight;

  if ((offset + height - 4) > max) {
    l.scrollTop += (offset + height - 4) - max;
  } else if (min && (offset - (height * 2) < min)) {
    l.scrollTop += offset - (height * 2) - min;
  }
}

// choose active element
function setActive(idx) {
  idx = Math.min(Math.max(0, idx), _tabs.length - 1);

  if (idx === _active) { return; }

  if (_active !== -1) {
    _tabs[_active].buttonHTML.className = '';
  }

  var btn = _tabs[idx].buttonHTML;
  btn.className = 'active';
  _active = idx;

  scrollTo(btn);
}

// Handle inputs
_elem.search.onkeydown = function (e) {
  console.log(e);
  switch (e.keyCode) {
    case 38: handleKeyUp();   break; // key up
    case 40: handleKeyDown(); break; // key down
    default: break;
  }
}

function handleKeyDown() {
  setActive(_active + 1);
}

function handleKeyUp() {
  setActive(_active - 1);
}

init();
<commit_msg>Avoided switch to handle actions, properly close popup and switch to window on openActiveTab()<commit_after>// Cached Globals and Aliases
var _tabs = [];
var _elem = document.all;
var _asyncLoadState = 0;
var _active = -1;
var _previousTabId = -1;
var _actions = [];
// info on currentTab
var _currentTab = null;
var _opts = {
  // Hide private navigation tabs form the results
  hideIncognito: true
};

// Activate focus on popup opening
_elem.search.focus();

function tryLoadTabs() {
  if (_asyncLoadState === 1) {
    chrome.tabs.query({}, loadTabs);
    _asyncLoadState = 0;
  } else {
    _asyncLoadState++;
  }
}

function setCurrent(tabs) {
  _currentTab = tabs[0];
  tryLoadTabs();
}

function setPrevious(tabId) {
  _previousTabId = tabId;
  tryLoadTabs();
}

function loadTabs(tabs) {
  _tabs = tabs.filter(tabsFilter);
  _tabs.sort(tabsSort);
  _tabs.forEach(genTab);
}

function tabsFilter(tab) {
  if (tab.id === _currentTab.id) { return false; }
  if (typeof tab.id === 'undefined') { return false; }
  return !(_opts.hideIncognito && tab.incognito);
}

function tabsSort(a, b) {
  if (a.id === _previousTabId) { return -1; }
  if (b.id === _previousTabId) { return 1; }
  if (a.windowId !== b.windowId) {
    if (a.windowId === _currentTab.windowId) {
      return -1;
    }
    if (b.windowId === _currentTab.windowId) {
      return 1;
    }
    return a.windowId - b.windowId;
  }
  return a.index - b.index;
}

// generate and append tab button
function genTab(tab, idx) {
  var title = document.createElement('h3');
  title.innerHTML = tab.title;

  var url = document.createElement('span');
  url.innerHTML = tab.url;

  var favIcon = document.createElement('div');
  favIcon.className = 'fav-icon';
  if (tab.windowId === _currentTab.windowId) {
    favIcon.className += ' current';
  }
  favIcon.style.backgroundImage = "url('" + tab.favIconUrl + "')";

  var button = document.createElement('button');
  button.id = 'tab-' + idx;
  button.dataset.id = tab.id;
  button.dataset.index = tab.index;
  button.appendChild(favIcon);
  button.appendChild(title);
  button.appendChild(url);
  _elem.list.appendChild(button);
  tab.buttonHTML = button;
}

function init() {
  var queryOptions = {
    'currentWindow': true,
    'active': true
  };
  chrome.tabs.query(queryOptions, setCurrent);

  //get previous tab from tabHistory
  chrome.runtime.sendMessage({}, setPrevious);
}

// Scroll to element if necessary
function scrollTo(elem) {
  var l = _elem.list;
  var min = l.scrollTop
  var max = l.clientHeight + min;
  var offset = elem.offsetTop;
  var height = elem.offsetHeight;

  if ((offset + height - 4) > max) {
    l.scrollTop += (offset + height - 4) - max;
  } else if (min && (offset - (height * 2) < min)) {
    l.scrollTop += offset - (height * 2) - min;
  }
}

// choose active element
function setActive(idx) {
  idx = Math.min(Math.max(0, idx), _tabs.length - 1);

  if (idx === _active) { return; }

  if (_active !== -1) {
    _tabs[_active].buttonHTML.className = '';
  }

  var btn = _tabs[idx].buttonHTML;
  btn.className = 'active';
  _active = idx;

  scrollTo(btn);
}

// Chrome Tabs Actions
function openActiveTab() {
  var activeTab = _tabs[_active];
  if (activeTab.windowId !== _currentTab.windowId) {
    chrome.windows.update(activeTab.windowId, { 'focused': true });
    window.close();
  }
  chrome.tabs.update(activeTab.id, { 'active': true });
}

// Handle inputs
_actions[13] = openActiveTab; // Key Enter
_actions[40] = function () {  // key Down
  setActive(_active + 1);
};
_actions[38] = function () {  // key Up
  setActive(_active - 1);
};

_elem.search.onkeydown = function (e) {
  console.log(e);
  var fn = _actions[e.keyCode];
  if (typeof fn !== 'function') { return; }
  fn(e);
}

init();
<|endoftext|>


<commit_before>var bgpage = chrome.extension.getBackgroundPage();

var wishlist = bgpage.wishlist;
var db = bgpage.db;

var newItemName;
window.onload = reload;

function addUI(iconIndex, idIndex){
    for(var i=0; i<wishlist.length; i++){
      $('.watchlist').append( "

"+wishlist[i].name+"

"+wishlist[i].price+" meso or less

" );
    }
}

function reload(){

    $.cookie.json = true;

    console.log("success");
    $('.watchlist').empty();

    wishlist = $.cookie('wishlist');
    console.log(wishlist);
    if( wishlist == undefined )
        wishlist = [];

    //for(var i=0; i<wishlist.length; i++){

    var iconIndex = {};
    var idIndex = {};

   var count = 0;

   $.each(wishlist, function(index,result){

      var id;

      for( var j=0; j < db.length; j++){
           if( result.name == db[j].b ){
              id = db[j].a;
              idIndex[db[j].b] = id;
              break;
           }
      }

      $.getJSON("http://maple.fm/api/items?id="+id, function(data){
          count = count+1;
          iconIndex[id] = data.item.icon;
          if( count==wishlist.length )
             addUI(iconIndex, idIndex);
      });

    });

    $('.add-item').submit( function(event){
          event.preventDefault();
          console.log("yea");
          id = -1;
          newItemName = $('.addbox').val();
          if(newItemName.length == 0){
              return false;
          }
          for( var j=0; j < db.length; j++){
             var str1 = newItemName;
             var str2 = db[j].b;
             if( str1.toLowerCase() == str2.toLowerCase() ){
                id = db[j].a;
                newItemName = str2;
                break;
             }
          }
          if(id==-1){
             swal({
               title: "Error!",
               text: "Item not found!",
               type: "error",
               confirmButtonText: "OK",
               confirmButtonColor: "#ffb484"
             });

             return false;
          }

          $.getJSON("http://maple.fm/api/items?id="+id, function(data){
              id = data.item.icon;
              $('.preview').css('left', 0);
              $('.page1').css('left', -332+'px');
              $('.pvicon').attr('src', 'http://maple.fm/static/image/icon/' + id +'.png');
              $('.pvname').text(newItemName);
          });
          return false;
      }
    );

    $('.add-price').submit( function(event){
          event.preventDefault();

          if($('.addprice').val().length == 0){
              return false;
          }

          bgpage.additem(newItemName, $('.addprice').val());

          $('.watchlist').append( "

"+newItemName+"

"+$('.addprice').val()+" meso or less

" );

          swal({
               title: "Done!",
               text: "The item has been added",
               type: "success",
               confirmButtonText: "OK",

          }, function(){
            $('.preview').css('left', 331+'px');
            $('.page1').css('left', 0+'px');
            $('.addbox').val("");
            $('.addprice').val("");
          });
          return false;
      }
    );
    $(document).on('click','.octicon-x', function(){
          bgpage.removeitem( $(this).attr('id') );
          $(this).parent().remove();
    });
}

<commit_msg>Added deletion animation<commit_after>var bgpage = chrome.extension.getBackgroundPage();

var wishlist = bgpage.wishlist;
var db = bgpage.db;

var newItemName;
window.onload = reload;

function addUI(iconIndex, idIndex){
    for(var i=0; i<wishlist.length; i++){
      $('.watchlist').append( "

"+wishlist[i].name+"

"+wishlist[i].price+" meso or less

" );
    }
}

function reload(){

    $.cookie.json = true;

    console.log("success");
    $('.watchlist').empty();

    wishlist = $.cookie('wishlist');
    console.log(wishlist);
    if( wishlist == undefined )
        wishlist = [];

    //for(var i=0; i<wishlist.length; i++){

    var iconIndex = {};
    var idIndex = {};

   var count = 0;

   $.each(wishlist, function(index,result){

      var id;

      for( var j=0; j < db.length; j++){
           if( result.name == db[j].b ){
              id = db[j].a;
              idIndex[db[j].b] = id;
              break;
           }
      }

      $.getJSON("http://maple.fm/api/items?id="+id, function(data){
          count = count+1;
          iconIndex[id] = data.item.icon;
          if( count==wishlist.length )
             addUI(iconIndex, idIndex);
      });

    });

    $('.add-item').submit( function(event){
          event.preventDefault();
          console.log("yea");
          id = -1;
          newItemName = $('.addbox').val();
          if(newItemName.length == 0){
              return false;
          }
          for( var j=0; j < db.length; j++){
             var str1 = newItemName;
             var str2 = db[j].b;
             if( str1.toLowerCase() == str2.toLowerCase() ){
                id = db[j].a;
                newItemName = str2;
                break;
             }
          }
          if(id==-1){
             swal({
               title: "Error!",
               text: "Item not found!",
               type: "error",
               confirmButtonText: "OK",
               confirmButtonColor: "#ffb484"
             });

             return false;
          }

          $.getJSON("http://maple.fm/api/items?id="+id, function(data){
              id = data.item.icon;
              $('.preview').css('left', 0);
              $('.page1').css('left', -332+'px');
              $('.pvicon').attr('src', 'http://maple.fm/static/image/icon/' + id +'.png');
              $('.pvname').text(newItemName);
          });
          return false;
      }
    );

    $('.add-price').submit( function(event){
          event.preventDefault();

          if($('.addprice').val().length == 0){
              return false;
          }

          bgpage.additem(newItemName, $('.addprice').val());

          $('.watchlist').append( "

"+newItemName+"

"+$('.addprice').val()+" meso or less

" );

          swal({
               title: "Done!",
               text: "The item has been added",
               type: "success",
               confirmButtonText: "OK",

          }, function(){
            $('.preview').css('left', 331+'px');
            $('.page1').css('left', 0+'px');
            $('.addbox').val("");
            $('.addprice').val("");
          });
          return false;
      }
    );
    $(document).on('click','.octicon-x', function(){
          bgpage.removeitem( $(this).attr('id') );
          var par = $(this).parent();
          par.hide('slow', function(){
            par.remove();
          });
    });
}

<|endoftext|>


<commit_before>function closePopup (event) {
  chrome.runtime.sendMessage({
    action: 'hide-preview'
  });
};

(function (win, doc) {
  var link = doc.querySelector('a.embedly-card');
  var url = decodeURIComponent(win.location.search.replace(/^\?/,''));

  if (/^https:/.test(url)) {
    link.parentNode.removeChild(link);
    var message = doc.createElement('p');
    message.innerHTML = 'Sorry, currently this extension does not work with HTTPS URLs, due to an issue with Embedly Cards, we are working on an update with Embedly\'s help!
Thanks for your patience.';

    doc.querySelector('.container').appendChild(message);
  } else {
    doc.querySelector('a.embedly-card').href = url;

    var script = doc.createElement('script');
    script.src = 'https://cdn.embedly.com/widgets/platform.js';

    doc.body.appendChild(script);

    doc.body.addEventListener('click', closePopup);
    doc.querySelector('button.close').addEventListener('click', closePopup);
  }
})(window, document);
<commit_msg>retain the close events outside the https condition<commit_after>function closePopup (event) {
  chrome.runtime.sendMessage({
    action: 'hide-preview'
  });
};

(function (win, doc) {
  var link = doc.querySelector('a.embedly-card');
  var url = decodeURIComponent(win.location.search.replace(/^\?/,''));

  if (/^https:/.test(url)) {
    link.parentNode.removeChild(link);
    var message = doc.createElement('p');
    message.innerHTML = 'Sorry, currently this extension does not work with HTTPS URLs, due to an issue with Embedly Cards, we are working on an update with Embedly\'s help!
Thanks for your patience.';

    doc.querySelector('.container').appendChild(message);
  } else {
    doc.querySelector('a.embedly-card').href = url;

    var script = doc.createElement('script');
    script.src = 'https://cdn.embedly.com/widgets/platform.js';

    doc.body.appendChild(script);

  }

  doc.body.addEventListener('click', closePopup);
  doc.querySelector('button.close').addEventListener('click', closePopup);
})(window, document);
<|endoftext|>


<commit_before>$(function() {

	function dmy() {
		var date = new Date();
		var d  = date.getDate();
		var day = (d < 10) ? '0' + d : d;
		var m = date.getMonth() + 1;
		var month = (m < 10) ? '0' + m : m;
		var yy = date.getYear();
		var year = (yy < 1000) ? yy + 1900 : yy;
		return year + "-" + month + "-" + day;
	}

	function getWeek(date) {
	  // Create a copy of this date object
	  var target  = new Date(date.valueOf());

	  // ISO week date weeks start on monday
	  // so correct the day number
	  var dayNr   = (date.getDay() + 6) % 7;

	  // ISO 8601 states that week 1 is the week
	  // with the first thursday of that year.
	  // Set the target date to the thursday in the target week
	  target.setDate(target.getDate() - dayNr + 3);

	  // Store the millisecond value of the target date
	  var firstThursday = target.valueOf();

	  // Set the target to the first thursday of the year
	  // First set the target to january first
	  target.setMonth(0, 1);
	  // Not a thursday? Correct the date to the next thursday
	  if (target.getDay() != 4) {
	    target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
	  }

	  // The weeknumber is the number of weeks between the
	  // first thursday of the year and the thursday in the target week
	  var week = 1 + Math.ceil((firstThursday - target) / 604800000);
	  return week < 10 ? '0' + week : week;
	}

	var base_url = $('body.controller-wiki #main-menu a.wiki').attr('href').replace(/\/(date_index|index)$/, '')

	var new_page = $('New page')
		.click(function() {
			var name = prompt("Page title:");
			if (name) {
			  window.location.href = base_url + "/" + encodeURI(name);
			}
		});

	var new_todo = $('New todo')
		.click(function() {
			var name = prompt("Todo list name:");
			var template = "* {{todo}} Task 1 — {{user(admin)}}\n* {{done}} Task 2 — {{user(admin)}}\n";
			if (name) {
				window.location.href = base_url + "/" + encodeURI(dmy() + ' Todo ' + name) + '?text=' + encodeURI(template);
			}
		});

	var new_minutes = $('New meeting minutes')
		.click(function() {
			var name = prompt("Meeting title:");
			var template = "Attendees:\n* \n\nAgenda:\n* \n\nMinutes:\n* ";
			if (name) {
				window.location.href = base_url + "/" + encodeURI(dmy() + ' Meeting ' + name) + '?text=' + encodeURI(template);
			}
		});

	var new_roadmap = $('New roadmap')
		.click(function() {
			var name = prompt("Roadmap title :", "Roadmap");
			var week = 7 * 24 * 3600 * 1000;
			var weeks = "";
			var emptyWeeks = "";
			var today = (new Date()).getTime();
			for (var i = 0; i < 10; i++) {
				var d = new Date(today + (i * week));
				weeks += "_. W" + getWeek(d) + " |";
				emptyWeeks += "       |";
			}
			var template = "|                  |" + weeks + "\n" +
				"| *_GROUP 1_* |\n" +
				"| {{issue(00001)}} |" + emptyWeeks  + "\n" +
				"| *_GROUP 2_* |\n" +
				"| {{issue(00001)}} |" + emptyWeeks  + "\n";
			if (name) {
				window.location.href = base_url + "/" + encodeURI(name) + '?text=' + encodeURI(template);
			}
		});

	$("body.controller-wiki #main #sidebar h3:first")
		.after("

")
		.after(new_roadmap)
		.after("
")
		.after(new_minutes)
		.after("
")
		.after(new_todo)
		.after("
")
		.after(new_page)
});<commit_msg>Fix when not present<commit_after>$(function() {

	function dmy() {
		var date = new Date();
		var d  = date.getDate();
		var day = (d < 10) ? '0' + d : d;
		var m = date.getMonth() + 1;
		var month = (m < 10) ? '0' + m : m;
		var yy = date.getYear();
		var year = (yy < 1000) ? yy + 1900 : yy;
		return year + "-" + month + "-" + day;
	}

	function getWeek(date) {
	  // Create a copy of this date object
	  var target  = new Date(date.valueOf());

	  // ISO week date weeks start on monday
	  // so correct the day number
	  var dayNr   = (date.getDay() + 6) % 7;

	  // ISO 8601 states that week 1 is the week
	  // with the first thursday of that year.
	  // Set the target date to the thursday in the target week
	  target.setDate(target.getDate() - dayNr + 3);

	  // Store the millisecond value of the target date
	  var firstThursday = target.valueOf();

	  // Set the target to the first thursday of the year
	  // First set the target to january first
	  target.setMonth(0, 1);
	  // Not a thursday? Correct the date to the next thursday
	  if (target.getDay() != 4) {
	    target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
	  }

	  // The weeknumber is the number of weeks between the
	  // first thursday of the year and the thursday in the target week
	  var week = 1 + Math.ceil((firstThursday - target) / 604800000);
	  return week < 10 ? '0' + week : week;
	}

	var base_url = $('body.controller-wiki #main-menu a.wiki').attr('href')

	if (base_url) {
		base_url = base_url.replace(/\/(date_index|index)$/, '');

		var new_page = $('New page')
			.click(function() {
				var name = prompt("Page title:");
				if (name) {
				  window.location.href = base_url + "/" + encodeURI(name);
				}
			});

		var new_todo = $('New todo')
			.click(function() {
				var name = prompt("Todo list name:");
				var template = "* {{todo}} Task 1 — {{user(admin)}}\n* {{done}} Task 2 — {{user(admin)}}\n";
				if (name) {
					window.location.href = base_url + "/" + encodeURI(dmy() + ' Todo ' + name) + '?text=' + encodeURI(template);
				}
			});

		var new_minutes = $('New meeting minutes')
			.click(function() {
				var name = prompt("Meeting title:");
				var template = "Attendees:\n* \n\nAgenda:\n* \n\nMinutes:\n* ";
				if (name) {
					window.location.href = base_url + "/" + encodeURI(dmy() + ' Meeting ' + name) + '?text=' + encodeURI(template);
				}
			});

		var new_roadmap = $('New roadmap')
			.click(function() {
				var name = prompt("Roadmap title :", "Roadmap");
				var week = 7 * 24 * 3600 * 1000;
				var weeks = "";
				var emptyWeeks = "";
				var today = (new Date()).getTime();
				for (var i = 0; i < 10; i++) {
					var d = new Date(today + (i * week));
					weeks += "_. W" + getWeek(d) + " |";
					emptyWeeks += "       |";
				}
				var template = "|                  |" + weeks + "\n" +
					"| *_GROUP 1_* |\n" +
					"| {{issue(00001)}} |" + emptyWeeks  + "\n" +
					"| *_GROUP 2_* |\n" +
					"| {{issue(00001)}} |" + emptyWeeks  + "\n";
				if (name) {
					window.location.href = base_url + "/" + encodeURI(name) + '?text=' + encodeURI(template);
				}
			});

		$("body.controller-wiki #main #sidebar h3:first")
			.after("

")
			.after(new_roadmap)
			.after("
")
			.after(new_minutes)
			.after("
")
			.after(new_todo)
			.after("
")
			.after(new_page);
	}
});<|endoftext|>


<commit_before>var items;
var formItems = [];
var total;
var modes;
var subId = $('#sub-id').val();
var daysDiff = 1;
$(document).ready(function() {

	// Getting mode
	$.post(modeUrl, {}, function(data) {
		modes = data;
	}, 'JSON');

	var itemsTemplate = _.template($('#item-list-template').html());
	processItem().then(function() {
		addDetail($('#item-id').val());
	});

	$('#reportrange').on('apply.daterangepicker', function (ev, picker) {
		var d = moment(endDate).diff(startDate, 'days');
		daysDiff = d + 1;
		processItem();
		$('#item-detail-table > tbody').html("");
		for (key in formItems) {
			var amount = (daysDiff / formItems[key]['rental_mode']) * formItems[key]['rate'];
			amount = Math.ceil(amount * 10) / 10;
			var total = amount * formItems[key]['qty'];
			formItems[key]['total'] = total;
			formItems[key]['total_format'] = formatNumber(total);
			formItems[key]['amount'] = formatNumber(amount);
			console.log(formItems[key]);
			$('#item-detail-table > tbody').append(itemDetailTemplate(formItems[key]));
		}
		computeTotal();
  });

	$('#reservation-form').submit(function(e) {
		e.preventDefault();
		if ($.isEmptyObject(formItems)) {
			errorMessage('You cannot submit because reservation is empty.');
		} else {
			var detail = $('#item-detail-container').clone().find('a').remove().end();
			$('#reservation-modal').find('.details').html(detail.html());
			$('#reservation-modal').find('#from-date').text(startDate);
			$('#reservation-modal').find('#to-date').text(endDate);
			$('#reservation-modal').modal('show');
		}
	});

	$('#btn-reset').click(function() {
		if (confirm('Are you sure to remove all?')) {
			removeAll();
			successMessage('All item detail has been removed');
			$('#item-detail-table > tbody > tr').fadeOut('slow', function() {
				$(this).remove();
			});
			computeTotal();
		}
	});

	$('#btn-confirm-modal').click(function() {
		var action = $('#reservation-form').attr('action');
		var form = {
			details: formItems,
			from: startDate,
			to: endDate,
			total: total,
			subscriber: subId
		};
		$('#reservation-modal').modal('hide');

		$.post(action, form, function(data) {
			console.log(data);
			if (data['result']) {
				window.location = reservationListUrl;
			} else {
				errorMessage(data['message']);
			}
		}, 'JSON');
	});

	$('#reservation-modal').on('hidden.bs.modal', function() {
		$('#reservation-modal').find('.details').html("");
	});

	function processItem() {
		var d = $.Deferred();
		var process;
		if ($('#shop-id').val() == "") {
			process = getItem($('#item-id').val(), startDate, endDate);
		} else {
			process = getShopItems($('#shop-id').val(), startDate, endDate);
		}
		process.then(function(data) {
			var itemData = {listItems: items};
			$('#item-list').html("");
			$('#item-list').append(itemsTemplate(itemData));
			d.resolve('success');
		});
		return d;
	}
});

function getShopItems(shopId, start, to) {
	var d = $.Deferred();
	$.post(shopItemsUrl, {shopId: shopId, start:start, to:to}, function(data) {
		if (data['result']) {
			items = data['items'];
			d.resolve('success');
		} else {
			errorMessage(data['message']);
			d.reject('failed');
		}
	}, 'JSON');
	return d.promise();
}

function getItem($id, start, to) {
	$.post(itemUrl, {id: id, start:start, to:to}, function(data) {
		if (data['result']) {
			items = data['items'];
		} else {
			errorMessage(data['message']);
		}
	}, 'JSON');
}

function findItem(id) {
	for (key in items) {
		if (items[key]['item_id'] == id) {
			return items[key];
		}
	}
	return false ;
}
function addDetail(id) {
	var item = findItem(id);
	if (item === false) {
		errorMessage('Item Not Found');
	} else if (isExistFormItem(id)) {
		errorMessage('Item already exist in detail');
	} else {
		// console.log(item['item_rental_mode']);
		var amount = ((daysDiff / parseFloat(item['item_rental_mode'])) * parseFloat(item['item_rate']));
		amount = Math.ceil(amount * 10) / 10;
		var total = item['item_qty'] * amount;
		var detail = {
			desc: item['item_desc'],
			qty: item['item_qty'],
			rate: item['item_rate'],
			total: total,
			rate_format: formatNumber(item['item_rate']),
			total_format: formatNumber(total),
			id: id,
			rental_mode: item['item_rental_mode'],
			mode:modes[item['item_rental_mode']],
			amount: formatNumber(amount)
		};
		formItems.push(detail);
		$('#item-detail-table > tbody').append(itemDetailTemplate(detail));
		successMessage('Added new item for reservation');
		computeTotal();
	}
}

function removeDetail(id) {
	var item = findItem(id);
	if (item === false) {
		return false;
	} else {
		for (key in formItems) {
			if (formItems[key]['id'] == id) {
				delete formItems[key];
				return true;
			}
		}
	}
}

function removeAll() {
	for (key in formItems) {
		delete formItems[key];
	}
}

function isExistFormItem(id) {
	for (key in formItems) {
		if (formItems[key]['id'] == id) {
			return true;
		}
	}
	return false;
}

function computeTotal() {
	total = 0;
	for(key in formItems) {
		total += parseFloat(formItems[key]['total']);
	}
	$('#total-label').text(formatNumber(total));
}

var itemDetailTemplate = _.template($('#item-detail-template').html());
$(document).on('click', '.btn-add', function() {
	var id = $(this).data('item-id');
	addDetail(id);
});

$(document).on('click', '.btn-view', function() {
	var id = $(this).data('item-id');
});

$(document).on('click', '.item-remove', function() {
	var row = $(this).closest('tr');
	var id = row.data('item-detail-row');
	if (confirm("Are you sure to delete Item # : " + id + "?")) {
		if (removeDetail(id)) {
			successMessage('Item # ' + id + ' Deleted');
			row.fadeOut('slow', function() {
				$(this).remove();
			});
			computeTotal();
		} else {
			errorMessage('Item Not Found');
		}
	}
});

$(document).on('click', '.change-qty', function() {
	var id = $(this).closest('tr').data('item-detail-row');
	var item = findItem(id);
	var qty = prompt("Change reservation quantity of item " + item['item_desc'] + ".", item['item_qty']);
	if (isNaN(qty)) {
		errorMessage('Quantity must be integer');
	} else if (qty > parseFloat(item['item_qty'])) {
		errorMessage('Quantity must not exceed the remaining quantity of item ' + item['item_desc']);
	} else if (qty <= 0) {
		errorMessage('Quantity must not less than 0');
	} else {
		successMessage('Quantity of item ' + item['item_desc'] + ' changed');
		for (key in formItems) {
			if (formItems[key]['id'] == id) {
				// var amount = (daysDiff / formItems[key]['rental_mode']) * formItems[key]['rate'];
				var subtotal = qty * formItems[key]['amount'];
				formItems[key]['qty'] = qty;
				formItems[key]['total'] = subtotal;
				computeTotal();
				$('[data-item-detail-row="'+id+'"]').find('span.label-subtotal').text(formatNumber(subtotal));
				$('[data-item-detail-row="'+id+'"]').find('span.label-qty').text(qty);
				return;
			}
		}
	}
});<commit_msg>Fix lessee reservation form script<commit_after>var items;
var formItems = [];
var total;
var modes;
var subId = $('#sub-id').val();
var daysDiff = 1;
$(document).ready(function() {

	// Getting mode
	$.post(modeUrl, {}, function(data) {
		modes = data;
		processItem().then(function() {
			addDetail($('#item-id').val());
		});
	}, 'JSON');

	var itemsTemplate = _.template($('#item-list-template').html());

	$('#reportrange').on('apply.daterangepicker', function (ev, picker) {
		var d = moment(endDate).diff(startDate, 'days');
		daysDiff = d;
		processItem().then(function() {
			$('#item-detail-table > tbody').html("");
			var message = "";
			var formItemsTemp = formItems;
			formItems = [];
			for (key in formItemsTemp) {
				var theItem = findItem(formItemsTemp[key]['id']);
				// console.log(theItem);
				if (theItem['item_qty_left'] == 0) {
					message += theItem['item_name'] + ", ";
				} else {
					formItemsTemp[key]['qty'] = (formItemsTemp[key]['qty'] <= theItem['item_qty_left']) ? formItemsTemp[key]['qty'] : theItem['item_qty_left'];
					var amount = (daysDiff / formItemsTemp[key]['rental_mode']) * formItemsTemp[key]['rate'];
					amount = Math.ceil(amount * 10) / 10;
					var total = amount * formItemsTemp[key]['qty'];
					formItemsTemp[key]['total'] = total;
					formItemsTemp[key]['total_format'] = formatNumber(total);
					formItemsTemp[key]['amount'] = formatNumber(amount);
					// console.log(formItemsTemp[key]);
					$('#item-detail-table > tbody').append(itemDetailTemplate(formItemsTemp[key]));
					formItems.push(formItemsTemp[key]);
				}
			}
			if (message != "") {
				errorMessage('Item ' + message + 'has been remove to details due to unavailable quantity');
			}
			computeTotal();
		});
  });

	$('#reservation-form').submit(function(e) {
		e.preventDefault();
		if ($.isEmptyObject(formItems)) {
			errorMessage('You cannot submit because reservation is empty.');
		} else {
			var detail = $('#item-detail-container').clone().find('a').remove().end();
			$('#reservation-modal').find('.details').html(detail.html());
			$('#reservation-modal').find('#from-date').text(startDate);
			$('#reservation-modal').find('#to-date').text(endDate);
			$('#reservation-modal').modal('show');
		}
	});

	$('#btn-reset').click(function() {
		if (confirm('Are you sure to remove all?')) {
			removeAll();
			successMessage('All item detail has been removed');
			$('#item-detail-table > tbody > tr').fadeOut('slow', function() {
				$(this).remove();
			});
			computeTotal();
		}
	});

	$('#btn-confirm-modal').click(function() {
		var action = $('#reservation-form').attr('action');
		var form = {
			details: formItems,
			from: startDate,
			to: endDate,
			total: total,
			subscriber: subId
		};
		$('#reservation-modal').modal('hide');

		$.post(action, form, function(data) {
			console.log(data);
			if (data['result']) {
				window.location = reservationListUrl;
			} else {
				errorMessage(data['message']);
			}
		}, 'JSON');
	});

	$('#reservation-modal').on('hidden.bs.modal', function() {
		$('#reservation-modal').find('.details').html("");
	});

	function processItem() {
		var d = $.Deferred();
		var process;
		if ($('#shop-id').val() == "") {
			process = getItem($('#item-id').val(), startDate, endDate);
		} else {
			process = getShopItems($('#shop-id').val(), startDate, endDate);
		}
		process.then(function(data) {
			// console.log(items);
			var itemData = {listItems: items};
			$('#item-list').html("");
			$('#item-list').append(itemsTemplate(itemData));
			d.resolve('success');
		});
		return d;
	}
});

function getShopItems(shopId, start, to) {
	var d = $.Deferred();
	$.post(shopItemsUrl, {shopId: shopId, start:start, to:to}, function(data) {
		if (data['result']) {
			items = data['items'];
			d.resolve('success');
		} else {
			errorMessage(data['message']);
			d.reject('failed');
		}
	}, 'JSON');
	return d.promise();
}

function getItem($id, start, to) {
	$.post(itemUrl, {id: id, start:start, to:to}, function(data) {
		if (data['result']) {
			items = data['items'];
		} else {
			errorMessage(data['message']);
		}
	}, 'JSON');
}

function findItem(id) {
	for (key in items) {
		if (items[key]['item_id'] == id) {
			return items[key];
		}
	}
	return false ;
}
function addDetail(id) {
	var item = findItem(id);
	if (item === false) {
		errorMessage('Item Not Found');
	} else if (isExistFormItem(id)) {
		errorMessage('Item already exist in detail');
	} else if (item['item_qty_left'] <= 0) {
		errorMessage('No more quantity left for this Item, change date for reservation');
	} else {
		// console.log(item['item_rental_mode']);
		var amount = ((daysDiff / parseFloat(item['item_rental_mode'])) * parseFloat(item['item_rate']));
		amount = Math.ceil(amount * 10) / 10;
		var total = item['item_qty'] * amount;
		var detail = {
			desc: item['item_desc'],
			qty: item['item_qty'],
			rate: item['item_rate'],
			total: total,
			rate_format: formatNumber(item['item_rate']),
			total_format: formatNumber(total),
			id: id,
			rental_mode: item['item_rental_mode'],
			mode:modes[item['item_rental_mode']],
			amount: formatNumber(amount)
		};
		formItems.push(detail);
		$('#item-detail-table > tbody').append(itemDetailTemplate(detail));
		successMessage('Added new item for reservation');
		computeTotal();
	}
}

function removeDetail(id) {
	var item = findItem(id);
	if (item === false) {
		return false;
	} else {
		for (key in formItems) {
			if (formItems[key]['id'] == id) {
				delete formItems[key];
				return true;
			}
		}
	}
}

function removeAll() {
	for (key in formItems) {
		delete formItems[key];
	}
}

function isExistFormItem(id) {
	for (key in formItems) {
		if (formItems[key]['id'] == id) {
			return true;
		}
	}
	return false;
}

function computeTotal() {
	total = 0;
	for(key in formItems) {
		total += parseFloat(formItems[key]['total']);
	}
	$('#total-label').text(formatNumber(total));
}

var itemDetailTemplate = _.template($('#item-detail-template').html());
$(document).on('click', '.btn-add', function() {
	var id = $(this).data('item-id');
	addDetail(id);
});

$(document).on('click', '.btn-view', function() {
	var id = $(this).data('item-id');
});

$(document).on('click', '.item-remove', function() {
	var row = $(this).closest('tr');
	var id = row.data('item-detail-row');
	if (confirm("Are you sure to delete Item # : " + id + "?")) {
		if (removeDetail(id)) {
			successMessage('Item # ' + id + ' Deleted');
			row.fadeOut('slow', function() {
				$(this).remove();
			});
			computeTotal();
		} else {
			errorMessage('Item Not Found');
		}
	}
});

$(document).on('click', '.change-qty', function() {
	var id = $(this).closest('tr').data('item-detail-row');
	var item = findItem(id);
	var qty = prompt("Change reservation quantity of item " + item['item_desc'] + ".", item['item_qty']);
	if (isNaN(qty)) {
		errorMessage('Quantity must be integer');
	} else if (qty > parseFloat(item['item_qty'])) {
		errorMessage('Quantity must not exceed the remaining quantity of item ' + item['item_desc']);
	} else if (qty <= 0) {
		errorMessage('Quantity must not less than 0');
	} else {
		successMessage('Quantity of item ' + item['item_desc'] + ' changed');
		for (key in formItems) {
			if (formItems[key]['id'] == id) {
				// var amount = (daysDiff / formItems[key]['rental_mode']) * formItems[key]['rate'];
				var subtotal = qty * formItems[key]['amount'];
				formItems[key]['qty'] = qty;
				formItems[key]['total'] = subtotal;
				computeTotal();
				$('[data-item-detail-row="'+id+'"]').find('span.label-subtotal').text(formatNumber(subtotal));
				$('[data-item-detail-row="'+id+'"]').find('span.label-qty').text(qty);
				return;
			}
		}
	}
});<|endoftext|>


<commit_before>$(function() {

    window.Endeavour.View.ListItemDetails = Backbone.Marionette.View.extend({

        tagName: 'div',
        className: 'list-item-details',

        events: {
            'click .reset':      'onClickReset',
            'click .save':       'onClickSave',
            'keypress input':    'onChangeInput',
            'keypress textarea': 'onChangeInput',
        },

        initialize: function() {

            this.emptyIndicatorExists = false;
            this.loadingIndicatorExists = false;
            this.detailsLoaded = false;

            this.views = [];
            this.els = {};

            this.els.summaryContainer = $('
Summary
<input class="fullwidth" />

');
            this.els.summaryInput = this.els.summaryContainer.find('input');

            this.datePicker = null;
            this.els.dueDateContainer = $('
Due Date
<input type="text" class="fullwidth" /><input type="hidden" />

');
            this.els.dueDateInput = this.els.dueDateContainer.find('input[type=text]');
            this.els.dueDateValue = this.els.dueDateContainer.find('input[type=hidden]');
            this.els.dueDateInput.on('focus', $.proxy(this.onDueDateFocus, this))
                                 .on('blur', $.proxy(this.onDueDateBlur, this));

            this.els.tagsContainer = $('
Tags
<input class="fullwidth" />

');
            this.els.tagsInput = this.els.tagsContainer.find('input');

            this.els.inputsContainer = $('

');

            this.els.buttons = $('

<button class="reset">Reset</button>

<button class="save">Save</button>

');
            this.els.resetButton = this.els.buttons.find('.reset');
            this.els.saveButton = this.els.buttons.find('.save');

            this.els.inputsContainer
                .append(this.els.summaryContainer)
                .append(this.els.dueDateContainer)
                .append(this.els.tagsContainer);

            this.els.header = $('

');
            this.els.detailsInput = $('<textarea class="item-details"></textarea>');

            this.els.header
                .append(this.els.inputsContainer)
                .append(this.els.buttons);

            this.$el
                .append(this.els.header)
                .append(this.els.detailsInput);

        },

        render: function() {

            if (this.model) {

                this.enableInputs();

                this.els.summaryInput.val(this.model.get('Summary'));

                var dueDate = this.model.getDueDate();
                if (dueDate) {
                    this.els.dueDateInput.val(dueDate.toDateString());
                    this.els.dueDateValue.val(dueDate.toJSON());
                }
                else {
                    this.els.dueDateInput.val('');
                    this.els.dueDateValue.val('');
                }

                if (this.model.detailsLoaded) {
                    this.els.detailsInput.val(this.model.details.get('Body'))
                }
                else {
                    this.els.detailsInput.val('');
                    this.model.loadDetails();
                }

            }
            else {
                this.disableInputs();
            }

            this.disableButtons();

            return this;

        },

        reset: function() {
            console.log('resetting');
            this.unsetModel();
            this.clearInputs();
            return this.render();
        },

        save: function() {

            // Save ListItem model
            var props = {
                Summary: this.els.summaryInput.val(),
                Due: this.els.dueDateValue.val(),
            };
            this.model.save(props, {patch: true})

            // Save ListItemDetails model
            this.model.details.save({Body: this.els.detailsInput.val()}, {patch: true});

            return this;

        },

        unsetModel: function() {
            if (this.model) this.unbindModelEvents();
            this.model = null;
            return this;
        },

        onListItemDestroy: function() {
            console.log('onListItemDestroy');
            return this.reset();
        },

        unbindModelEvents: function() {
            this.model.off('loaded:details', this.onDetailsLoaded, this);
            this.model.off('destroy', this.onListItemDestroy, this);
            return this;
        },

        bindModelEvents: function() {
            this.model.on('loaded:details', this.onDetailsLoaded, this);
            this.model.on('destroy', this.onListItemDestroy, this);
            return this;
        },

        setModel: function(model) {

            if (this.model) {
                this.unbindModelEvents();
            }

            this.model = model;
            this.render();

            this.bindModelEvents();

            return this;

        },

        disableButtons: function() {
            this.els.resetButton.attr('disabled', 'disabled');
            this.els.saveButton.attr('disabled', 'disabled');
            return this;
        },

        enableButtons: function() {
            this.els.resetButton.removeAttr('disabled');
            this.els.saveButton.removeAttr('disabled');
            return this;
        },

        onChangeInput: function() {
            this.enableButtons();
            return this;
        },

        onClickReset: function() {
            return this.render();
        },

        onClickSave: function() {
            return this.save();
        },

        onDetailsLoaded: function() {
            return this.render()
        },

        onDueDateFocus: function(ev) {

            if (this.datePicker) return;

            var datePicker = this.datePicker = new Endeavour.View.DatePicker;

            this.els.dueDateContainer.append(datePicker.render().$el);

            datePicker.on('date-selected', function(date) {
                this.els.dueDateInput.val(date.toDateString());
                this.els.dueDateValue.val(date.toJSON());
                this.closeDatePicker();
                this.enableButtons();
            }, this);

            this.bindBodyClickEvents();

        },

        onDueDateBlur: function() {

        },

        onBodyClick: function(ev) {
            console.log($(ev.target), this.els.dueDateInput)
            if ($(ev.target)[0] === this.els.dueDateInput[0]) return;
            this.unbindBodyClickEvents();
            this.closeDatePicker();
        },

        closeDatePicker: function() {
            this.datePicker.close();
            this.datePicker = null;
        },

        bindBodyClickEvents: function() {
            $('body').on('click', $.proxy(this.onBodyClick, this));
        },

        unbindBodyClickEvents: function() {
            $('body').off('click', $.proxy(this.onBodyClick, this));
        },

        clearInputs: function() {
            this.els.summaryInput.val('');
            this.els.dueDateInput.val('');
            this.els.dueDateValue.val('');
            this.els.tagsInput.val('');
            this.els.detailsInput.val('');
            return this;
        },

        enableInputs: function() {
            this.els.summaryInput.removeAttr('disabled');
            this.els.dueDateInput.removeAttr('disabled');
            this.els.tagsInput.removeAttr('disabled');
            this.els.detailsInput.removeAttr('disabled');
            return this;
        },

        disableInputs: function() {
            this.els.summaryInput.attr('disabled', 'disabled');
            this.els.dueDateInput.attr('disabled', 'disabled');
            this.els.tagsInput.attr('disabled', 'disabled');
            this.els.detailsInput.attr('disabled', 'disabled');
            return this;
        },

    });

});<commit_msg>Due date container bug<commit_after>$(function() {

    window.Endeavour.View.ListItemDetails = Backbone.Marionette.View.extend({

        tagName: 'div',
        className: 'list-item-details',

        events: {
            'click .reset':      'onClickReset',
            'click .save':       'onClickSave',
            'keypress input':    'onChangeInput',
            'keypress textarea': 'onChangeInput',
        },

        initialize: function() {

            this.emptyIndicatorExists = false;
            this.loadingIndicatorExists = false;
            this.detailsLoaded = false;

            this.views = [];
            this.els = {};

            this.els.summaryContainer = $('
Summary
<input class="fullwidth" />

');
            this.els.summaryInput = this.els.summaryContainer.find('input');

            this.datePicker = null;
            this.els.dueDateContainer = $('
Due Date
<input type="text" class="fullwidth" /><input type="hidden" />

');
            this.els.dueDateInput = this.els.dueDateContainer.find('input[type=text]');
            this.els.dueDateValue = this.els.dueDateContainer.find('input[type=hidden]');

            this.els.dueDateContainer.on('click', function(ev){ev.stopImmediatePropagation();});
            this.els.dueDateInput.on('focus', $.proxy(this.onDueDateFocus, this))
                                 .on('blur', $.proxy(this.onDueDateBlur, this));

            this.els.tagsContainer = $('
Tags
<input class="fullwidth" />

');
            this.els.tagsInput = this.els.tagsContainer.find('input');

            this.els.inputsContainer = $('

');

            this.els.buttons = $('

<button class="reset">Reset</button>

<button class="save">Save</button>

');
            this.els.resetButton = this.els.buttons.find('.reset');
            this.els.saveButton = this.els.buttons.find('.save');

            this.els.inputsContainer
                .append(this.els.summaryContainer)
                .append(this.els.dueDateContainer)
                .append(this.els.tagsContainer);

            this.els.header = $('

');
            this.els.detailsInput = $('<textarea class="item-details"></textarea>');

            this.els.header
                .append(this.els.inputsContainer)
                .append(this.els.buttons);

            this.$el
                .append(this.els.header)
                .append(this.els.detailsInput);

        },

        render: function() {

            if (this.model) {

                this.enableInputs();

                this.els.summaryInput.val(this.model.get('Summary'));

                var dueDate = this.model.getDueDate();
                if (dueDate) {
                    this.els.dueDateInput.val(dueDate.toDateString());
                    this.els.dueDateValue.val(dueDate.toJSON());
                }
                else {
                    this.els.dueDateInput.val('');
                    this.els.dueDateValue.val('');
                }

                if (this.model.detailsLoaded) {
                    this.els.detailsInput.val(this.model.details.get('Body'))
                }
                else {
                    this.els.detailsInput.val('');
                    this.model.loadDetails();
                }

            }
            else {
                this.disableInputs();
            }

            this.disableButtons();

            return this;

        },

        reset: function() {
            console.log('resetting');
            this.unsetModel();
            this.clearInputs();
            return this.render();
        },

        save: function() {

            // Save ListItem model
            var props = {
                Summary: this.els.summaryInput.val(),
                Due: this.els.dueDateValue.val(),
            };
            this.model.save(props, {patch: true})

            // Save ListItemDetails model
            this.model.details.save({Body: this.els.detailsInput.val()}, {patch: true});

            return this;

        },

        unsetModel: function() {
            if (this.model) this.unbindModelEvents();
            this.model = null;
            return this;
        },

        onListItemDestroy: function() {
            console.log('onListItemDestroy');
            return this.reset();
        },

        unbindModelEvents: function() {
            this.model.off('loaded:details', this.onDetailsLoaded, this);
            this.model.off('destroy', this.onListItemDestroy, this);
            return this;
        },

        bindModelEvents: function() {
            this.model.on('loaded:details', this.onDetailsLoaded, this);
            this.model.on('destroy', this.onListItemDestroy, this);
            return this;
        },

        setModel: function(model) {

            if (this.model) {
                this.unbindModelEvents();
            }

            this.model = model;
            this.render();

            this.bindModelEvents();

            return this;

        },

        disableButtons: function() {
            this.els.resetButton.attr('disabled', 'disabled');
            this.els.saveButton.attr('disabled', 'disabled');
            return this;
        },

        enableButtons: function() {
            this.els.resetButton.removeAttr('disabled');
            this.els.saveButton.removeAttr('disabled');
            return this;
        },

        onChangeInput: function() {
            this.enableButtons();
            return this;
        },

        onClickReset: function() {
            return this.render();
        },

        onClickSave: function() {
            return this.save();
        },

        onDetailsLoaded: function() {
            return this.render()
        },

        onDueDateFocus: function(ev) {

            if (this.datePicker) return;

            var datePicker = this.datePicker = new Endeavour.View.DatePicker;

            this.els.dueDateContainer.append(datePicker.render().$el);

            datePicker.on('date-selected', function(date) {
                this.els.dueDateInput.val(date.toDateString());
                this.els.dueDateValue.val(date.toJSON());
                this.closeDatePicker();
                this.enableButtons();
            }, this);

            this.bindBodyClickEvents();

        },

        onDueDateBlur: function() {

        },

        onBodyClick: function(ev) {
            console.log($(ev.target), this.els.dueDateInput)
            if ($(ev.target)[0] === this.els.dueDateInput[0]) return;
            this.unbindBodyClickEvents();
            this.closeDatePicker();
        },

        closeDatePicker: function() {
            this.datePicker.close();
            this.datePicker = null;
        },

        bindBodyClickEvents: function() {
            $('body').on('click', $.proxy(this.onBodyClick, this));
        },

        unbindBodyClickEvents: function() {
            $('body').off('click', $.proxy(this.onBodyClick, this));
        },

        clearInputs: function() {
            this.els.summaryInput.val('');
            this.els.dueDateInput.val('');
            this.els.dueDateValue.val('');
            this.els.tagsInput.val('');
            this.els.detailsInput.val('');
            return this;
        },

        enableInputs: function() {
            this.els.summaryInput.removeAttr('disabled');
            this.els.dueDateInput.removeAttr('disabled');
            this.els.tagsInput.removeAttr('disabled');
            this.els.detailsInput.removeAttr('disabled');
            return this;
        },

        disableInputs: function() {
            this.els.summaryInput.attr('disabled', 'disabled');
            this.els.dueDateInput.attr('disabled', 'disabled');
            this.els.tagsInput.attr('disabled', 'disabled');
            this.els.detailsInput.attr('disabled', 'disabled');
            return this;
        },

    });

});<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, IT Services, Stockholm University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of Stockholm University nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

if (!("JST" in window) || "JST" === undefined) {
  window.JST = {};
}

JST['map/infoWindow/building'] = _.template(" \
<% if (hasElevators === true) { %> \

\

\

<%= i18n.t('map.infoWindow.elevator.exists') %>
\

\
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.elevator.noexists') %>
\

 \
<% } %> \
<% if (tFloors != '') { %> \

\

\

<%= i18n.t('map.infoWindow.toilet.exists') + ' ' + tFloors %>
\

 \
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.toilet.noexists') %>
\

\
<% } %> \
<% if (hasEntrances === true) { %> \

\

\

\
      <%= i18n.t('map.infoWindow.entrance.show') %> \
      <%= i18n.t('map.infoWindow.entrance.hide') %> \

\

\
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.entrance.noexists') %>
\

 \
<% } %> \
");

JST['map/infoWindow/organization'] = _.template(" \

\
    <% if (address != null) { %> \

\
        <%= address %>
\
      <% } %> \
      <% if (postalCode != null) { %> \
        <%= postalCode %>  \
      <% } %> \
      <% if (postalCity != null) { %> \
        <%= postalCity %>\
      <% } %>\

\
    \
    <% if (telephoneNumber != null) { %> \

\
        <%= i18n.t('map.infoWindow.organization.telephoneNumber') %>:  \
        <a href='tel:<%= telephoneNumber %>' id='department-phone-link'><%= telephoneNumber %>\

 \
    <% } %> \
    <% if (webAddress != null) { %> \

\
        <%= i18n.t('map.infoWindow.organization.webAddress') %>:  \
        <a href='<%= webAddress %>' id='department-website-link'><%= webAddressShort %>\

\
    <% } %> \
    <% if (mailAddresses != '') { %> \

\
        <%= i18n.t('map.infoWindow.organization.mailAddresses') %>:  \
        <% for(var mailAddress in mailAddresses) { %> \
          <a href='mailto:<%= mailAddresses[mailAddress] %>' id='department-mail-link'><%= mailAddresses[mailAddress] %>\
        <% } %>\

\
    <% } %> \

\
");

JST['map/infoWindow'] = _.template(" \

\

<%= name %>
\

\
  <% if (model.has('buildingName')) { %>\
    <%= model.get('buildingName') %>
\
  <% } %>\
  <% if (itemText != null) { %>\
    <%= itemText  %>\
  <% } %> \
  <% if(model.get('type') === 'organization') { %> \
    <%= JST['map/infoWindow/organization']({telephoneNumber: telephoneNumber, webAddress: webAddress, mailAddresses: mailAddresses, address: address, postalCode: postalCode, postalCity: postalCity, webAddressShort: webAddressShort}) %> \
  <% } %> \

\
  <% if (model.get('type') === 'building'){ %> \
    <%= JST['map/infoWindow/building']({hasElevators: hasElevators, tFloors: tFloors, hasEntrances: hasEntrances}) %> \
  <% } %>\
  <% if (model.get('type') === 'auditorium' && model.get('handicapAdapted') === true) { %> \

\

\

<%= i18n.t('map.infoWindow.hearing_loop.exists') %>
\

\
  <% } else if (model.get('type') === 'auditorium') { %> \

\

\

<%= i18n.t('map.infoWindow.hearing_loop.noexists') %>
\

\
  <% } %> \

\
  \
  <% if (displayDirections === true) { %> \

 \

 \
      <a class='kd-button kd-button-left dir-button' href='javascript:void(0)' id='walking' \
         title='<%= i18n.t('map.infoWindow.walking') %>'> \
         \
       \
      <a class='kd-button kd-button-mid dir-button' href='javascript:void(0)' id='bicycling' \
         title='<%= i18n.t('map.infoWindow.bicycling') %>'> \
         \
      \
      <a class='kd-button kd-button-mid dir-button' href='javascript:void(0)' id='publicTransp' \
         title='<%= i18n.t('map.infoWindow.publicTransit') %>'> \
         \
       \
      <a class='kd-button kd-button-right dir-button' href='javascript:void(0)' id='driving' \
         title='<%= i18n.t('map.infoWindow.car') %>'> \
         \
       \

 \

\
  <% } %> \

 \
");
<commit_msg>MOB-281 Added target="_blank" to department website link so the external browser warning is shown<commit_after>/*
 * Copyright (c) 2013, IT Services, Stockholm University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of Stockholm University nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

if (!("JST" in window) || "JST" === undefined) {
  window.JST = {};
}

JST['map/infoWindow/building'] = _.template(" \
<% if (hasElevators === true) { %> \

\

\

<%= i18n.t('map.infoWindow.elevator.exists') %>
\

\
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.elevator.noexists') %>
\

 \
<% } %> \
<% if (tFloors != '') { %> \

\

\

<%= i18n.t('map.infoWindow.toilet.exists') + ' ' + tFloors %>
\

 \
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.toilet.noexists') %>
\

\
<% } %> \
<% if (hasEntrances === true) { %> \

\

\

\
      <%= i18n.t('map.infoWindow.entrance.show') %> \
      <%= i18n.t('map.infoWindow.entrance.hide') %> \

\

\
<% } else { %> \

\

\

<%= i18n.t('map.infoWindow.entrance.noexists') %>
\

 \
<% } %> \
");

JST['map/infoWindow/organization'] = _.template(" \

\
    <% if (address != null) { %> \

\
        <%= address %>
\
      <% } %> \
      <% if (postalCode != null) { %> \
        <%= postalCode %>  \
      <% } %> \
      <% if (postalCity != null) { %> \
        <%= postalCity %>\
      <% } %>\

\
    \
    <% if (telephoneNumber != null) { %> \

\
        <%= i18n.t('map.infoWindow.organization.telephoneNumber') %>:  \
        <a href='tel:<%= telephoneNumber %>' id='department-phone-link'><%= telephoneNumber %>\

 \
    <% } %> \
    <% if (webAddress != null) { %> \

\
        <%= i18n.t('map.infoWindow.organization.webAddress') %>:  \
        <a href='<%= webAddress %>' id='department-website-link' target='_blank'><%= webAddressShort %>\

\
    <% } %> \
    <% if (mailAddresses != '') { %> \

\
        <%= i18n.t('map.infoWindow.organization.mailAddresses') %>:  \
        <% for(var mailAddress in mailAddresses) { %> \
          <a href='mailto:<%= mailAddresses[mailAddress] %>' id='department-mail-link'><%= mailAddresses[mailAddress] %>\
        <% } %>\

\
    <% } %> \

\
");

JST['map/infoWindow'] = _.template(" \

\

<%= name %>
\

\
  <% if (model.has('buildingName')) { %>\
    <%= model.get('buildingName') %>
\
  <% } %>\
  <% if (itemText != null) { %>\
    <%= itemText  %>\
  <% } %> \
  <% if(model.get('type') === 'organization') { %> \
    <%= JST['map/infoWindow/organization']({telephoneNumber: telephoneNumber, webAddress: webAddress, mailAddresses: mailAddresses, address: address, postalCode: postalCode, postalCity: postalCity, webAddressShort: webAddressShort}) %> \
  <% } %> \

\
  <% if (model.get('type') === 'building'){ %> \
    <%= JST['map/infoWindow/building']({hasElevators: hasElevators, tFloors: tFloors, hasEntrances: hasEntrances}) %> \
  <% } %>\
  <% if (model.get('type') === 'auditorium' && model.get('handicapAdapted') === true) { %> \

\

\

<%= i18n.t('map.infoWindow.hearing_loop.exists') %>
\

\
  <% } else if (model.get('type') === 'auditorium') { %> \

\

\

<%= i18n.t('map.infoWindow.hearing_loop.noexists') %>
\

\
  <% } %> \

\
  \
  <% if (displayDirections === true) { %> \

 \

 \
      <a class='kd-button kd-button-left dir-button' href='javascript:void(0)' id='walking' \
         title='<%= i18n.t('map.infoWindow.walking') %>'> \
         \
       \
      <a class='kd-button kd-button-mid dir-button' href='javascript:void(0)' id='bicycling' \
         title='<%= i18n.t('map.infoWindow.bicycling') %>'> \
         \
      \
      <a class='kd-button kd-button-mid dir-button' href='javascript:void(0)' id='publicTransp' \
         title='<%= i18n.t('map.infoWindow.publicTransit') %>'> \
         \
       \
      <a class='kd-button kd-button-right dir-button' href='javascript:void(0)' id='driving' \
         title='<%= i18n.t('map.infoWindow.car') %>'> \
         \
       \

 \

\
  <% } %> \

 \
");
<|endoftext|>


<commit_before>const fs = require('fs')
const fse = require('fs-extra')
const { execSync } = require('child_process')

process.chdir(__dirname)

const outDir = '../../../'
const bowerDir = '../../../react-uwp-bower'

const outDirOptions = { cwd: outDir, stdio: 'inherit' }
const bowerDirOptions = { cwd: bowerDir, stdio: 'inherit' }

module.exports = function buildBowerRelease(version) {
  if (!fs.existsSync(bowerDir)) {
    execSync('git clone https://github.com/myxvisual/react-uwp-bower', outDirOptions)
  }

  fse.copySync('../public/static', bowerDir, { overwrite: true })
  execSync(`git add -A && git commit --allow-empty -m ${(version && version.slice(1)) || 'Update bower files'} && git tag ${version} && git push origin --tags`, bowerDirOptions)
  console.log('bower-release is finished')
}
<commit_msg>chore: Update bower-release-build script<commit_after>const fs = require('fs')
const fse = require('fs-extra')
const { execSync } = require('child_process')

process.chdir(__dirname)

const outDir = '../../../'
const bowerDir = '../../../react-uwp-bower'

const outDirOptions = { cwd: outDir, stdio: 'inherit' }
const bowerDirOptions = { cwd: bowerDir, stdio: 'inherit' }

module.exports = function buildBowerRelease(version) {
  if (!fs.existsSync(bowerDir)) {
    execSync('git clone https://github.com/myxvisual/react-uwp-bower', outDirOptions)
  }

  fse.copySync('../public/static', bowerDir, { overwrite: true })
  try {
    execSync(`git add -A && git commit --allow-empty -m ${(version && version.slice(1)) || 'Update bower files'} && git tag ${version} && git push origin --tags`, bowerDirOptions)
  } catch (err) {
    console.error(err)
  }
  console.log('bower-release is finished')
}
<|endoftext|>


<commit_before>var connect = require('connect')
  , http = require('http')
  , url = require('url')
  , fs = require('fs')
  , path = require('path')
  , net = require('net')
  , WSS = require('websocket').server;

var app = connect()
  .use(connect.static('public'))
  .use(connect.query())
  .use(function (req, res, next) {
    var _url = url.parse(req.url)
    console.log(_url);
    if (/^\/(fonts|pixmaps)\/{0,1}$/.test(_url.pathname))
      fs.readdir(path.join(__dirname, 'public', _url.pathname), function (err, dir) {
        if (err)
          return next(err);
        if (req.query.filter)
          try {
            var re = new RegExp('^'+req.query.filter.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1").replace(/\\([*?])/g, '.$1')+'\..*$');
            console.log(re);
            dir = dir.filter(re.test.bind(re));
          } catch (e) {
            return next(e);
          }
        res.end(JSON.stringify(dir));
      });
    else
      next()
  })

var server = http.createServer(app).listen(3000);

var screens = [41];

var wss = new WSS({
    httpServer: server
  , autoAcceptConnections: false
});

wss.on('request', function (req) {
  var screen = screens.shift();

  if (!(req.origin && screen)) {
    console.log('reject');
    return req.reject();
  }

  var con = req.accept('x11-proxy', req.origin)
    , sockets = {};

  console.log('connected', screen);
  con.sendUTF('SCR ' + screen);
  var local_socket = net.createServer(function (socket) {
    var id = socket.remotePort;
    sockets[id] = socket;
    console.log('New client', id);
    con.sendUTF('NEW ' + id);
    socket.on('close', function () {
      con.sendUTF('END ' + id);
      delete sockets[id];
    });
    socket.on('data', function (data) {
      var buffer = new Buffer(data.length + 2);
      data.copy(buffer, 2);
      buffer.writeUInt16BE(id, 0);
      con.sendBytes(buffer);
    });
  }).listen(6000 + screen);
  con.on('message', function (message) {
    if (message.type === 'utf8') {
      console.log('data');
    } else {
      var data = message.binaryData;
      sockets[data.readUInt16LE(0)].write(data.slice(2));
    }
  });
  con.on('close', function () {
    console.log('closed');
    local_socket.close();
    screens.push(screen);
  });
});

<commit_msg>Force all tcp connections to end when websocket client disconnects<commit_after>var connect = require('connect')
  , http = require('http')
  , url = require('url')
  , fs = require('fs')
  , path = require('path')
  , net = require('net')
  , WSS = require('websocket').server;

var app = connect()
  .use(connect.static('public'))
  .use(connect.query())
  .use(function (req, res, next) {
    var _url = url.parse(req.url)
    console.log(_url);
    if (/^\/(fonts|pixmaps)\/{0,1}$/.test(_url.pathname))
      fs.readdir(path.join(__dirname, 'public', _url.pathname), function (err, dir) {
        if (err)
          return next(err);
        if (req.query.filter)
          try {
            var re = new RegExp('^'+req.query.filter.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1").replace(/\\([*?])/g, '.$1')+'\..*$');
            console.log(re);
            dir = dir.filter(re.test.bind(re));
          } catch (e) {
            return next(e);
          }
        res.end(JSON.stringify(dir));
      });
    else
      next()
  })

var server = http.createServer(app).listen(3000);

var screens = [41];

var wss = new WSS({
    httpServer: server
  , autoAcceptConnections: false
});

wss.on('request', function (req) {
  var screen = screens.shift();

  if (!(req.origin && screen)) {
    console.log('reject');
    return req.reject();
  }

  var con = req.accept('x11-proxy', req.origin)
    , sockets = {};

  console.log('connected', screen);
  con.sendUTF('SCR ' + screen);
  var local_socket = net.createServer(function (socket) {
    var id = socket.remotePort;
    sockets[id] = socket;
    console.log('New client', id);
    con.sendUTF('NEW ' + id);
    socket.on('close', function () {
      con.sendUTF('END ' + id);
      delete sockets[id];
    });
    socket.on('data', function (data) {
      var buffer = new Buffer(data.length + 2);
      data.copy(buffer, 2);
      buffer.writeUInt16BE(id, 0);
      con.sendBytes(buffer);
    });
  }).listen(6000 + screen);
  con.on('message', function (message) {
    if (message.type === 'utf8') {
      console.log('data');
    } else {
      var data = message.binaryData;
      sockets[data.readUInt16LE(0)].write(data.slice(2));
    }
  });
  con.on('close', function () {
    console.log('closed');
    Object.keys(sockets).forEach(function (id) {
      sockets[id].end();
    })
    local_socket.close();
    screens.push(screen);
  });
});

<|endoftext|>