<commit_before>/*
 * Etalage -- Open Data POIs portal
 * By: Emmanuel Raviart <eraviart@easter-eggs.com>
 *
 * Copyright (C) 2011, 2012 Easter-eggs
 * http://gitorious.org/infos-pratiques/etalage
 *
 * This file is part of Etalage.
 *
 * Etalage is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Etalage is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

var etalage = etalage || {};

etalage.bind = (function ($) {
    var $loadingGif;
    var isLoaded = false;

    function preloadLoadingGif() {
        image = new Image();
        image.src = etalage.miscUrl + 'please-wait.gif';
        image.alt = 'Chargement...';

        $loadingGif = $("<span>", {class: "loading"}).append($(image));
        $loadingGif.addClass('loading');

        isLoaded = true;
    }

    function loadingGif() {
        if (!isLoaded) {
            preloadLoadingGif();
        }

        $('a.internal').on('click', appendLoadingGif);
        $('#search-form').on('submit', appendLoadingGif);
    }

    function appendLoadingGif(event) {
        $('#search-form .control-group .controls').last().append($loadingGif);
        $loadingGif.data('activeUrl', document.location);

        setTimeout(function () {
            if (typeof($loadingGif) !== "undefined" &&
                    $loadingGif !== null &&
                    document.location == $loadingGif.data('activeUrl')) {
                $loadingGif.detach();
                clearTimeout();
            }
        }, 300);
    }

    function toggleCategories() {
        if (!isLoaded) {
            preloadLoadingGif();
        }

        $("#search-form input[name='category'][type='checkbox']").on('change', function(event) {
            var action = $("#search-form").attr('action');
            var queryString = $("#search-form").serialize();

            $('#search-form .form-actions').last().append($loadingGif);

            if (typeof etalage.rpc !== "undefined" && etalage.rpc !== null) {
                etalage.rpc.requestNavigateTo(action + '?' + queryString);
                return false;
            } else {
                document.location = action + "?" + queryString;
            }
        });
    }

    return {
        loadingGif: loadingGif,
        toggleCategories: toggleCategories
    };
})(jQuery);

<commit_msg>Fix JSHint error.<commit_after>/*
 * Etalage -- Open Data POIs portal
 * By: Emmanuel Raviart <eraviart@easter-eggs.com>
 *
 * Copyright (C) 2011, 2012 Easter-eggs
 * http://gitorious.org/infos-pratiques/etalage
 *
 * This file is part of Etalage.
 *
 * Etalage is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Etalage is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

var etalage = etalage || {};

etalage.bind = (function ($) {
    var $loadingGif;
    var isLoaded = false;

    function preloadLoadingGif() {
        image = new Image();
        image.src = etalage.miscUrl + 'please-wait.gif';
        image.alt = 'Chargement...';

        $loadingGif = $("<span>", {"class": "loading"}).append($(image));
        $loadingGif.addClass('loading');

        isLoaded = true;
    }

    function loadingGif() {
        if (!isLoaded) {
            preloadLoadingGif();
        }

        $('a.internal').on('click', appendLoadingGif);
        $('#search-form').on('submit', appendLoadingGif);
    }

    function appendLoadingGif(event) {
        $('#search-form .control-group .controls').last().append($loadingGif);
        $loadingGif.data('activeUrl', document.location);

        setTimeout(function () {
            if (typeof($loadingGif) !== "undefined" &&
                    $loadingGif !== null &&
                    document.location == $loadingGif.data('activeUrl')) {
                $loadingGif.detach();
                clearTimeout();
            }
        }, 300);
    }

    function toggleCategories() {
        if (!isLoaded) {
            preloadLoadingGif();
        }

        $("#search-form input[name='category'][type='checkbox']").on('change', function(event) {
            var action = $("#search-form").attr('action');
            var queryString = $("#search-form").serialize();

            $('#search-form .form-actions').last().append($loadingGif);

            if (typeof etalage.rpc !== "undefined" && etalage.rpc !== null) {
                etalage.rpc.requestNavigateTo(action + '?' + queryString);
                return false;
            } else {
                document.location = action + "?" + queryString;
            }
        });
    }

    return {
        loadingGif: loadingGif,
        toggleCategories: toggleCategories
    };
})(jQuery);

<|endoftext|>


<commit_before> 'use strict'

 const {type} = require('message-type')
 const canvasApi = require('../canvasApi')
 const Promise = require('bluebird')
 const config = require('../server/init/configuration')
 const log = require('../server/init/logging')
 const ugParser = require('./ugParser')
 const calcSisForOmregistrerade = require('./calcSisForOmregistrerade')
 require('colors')
 const createCsvFile = require('./createCsvFile')
 const csvVol = config.full.azure.csvBlobName
 const csvDir = config.full.localFile.csvDir

 function _parseKey (msg) {
   const {ug1Name, _desc} = msg
   const {userType} = _desc

   if (userType === type.students) {
     return Promise.resolve(ugParser.parseKeyStudent(ug1Name))
   }

   if (userType === type.teachers || userType === type.assistants || userType === type.courseresponsibles) {
     return Promise.resolve(ugParser.parseKeyTeacher(ug1Name))
   }

   log.error('Course code not parsable from Key. type, ', userType + ' ug1Name, ' + ug1Name)
   return Promise.reject(Error('Key parse error, type, ' + userType + ' ug1Name, ' + ug1Name))
 }

 function _process (msg) {
   let sisCourseCodeFunction
   if (msg._desc.userType === type.omregistrerade) {
     log.info('using calcSisForOmregistrerade')
     sisCourseCodeFunction = calcSisForOmregistrerade
   } else {
     log.info('using _parseKey')
     sisCourseCodeFunction = _parseKey
   }

   return sisCourseCodeFunction(msg)
    .then(() => createCsvFile(msg, sisCourseCode, csvDir, csvVol))
    .then(csvObject => {
      log.info('FileName: ', csvObject.csvFileName)
      return csvObject.csvFileName
    })
    .then(fileName => canvasApi.sendCsvFile(fileName, true))
    .then(canvasReturnValue => {
      let document = {msg: msg, resp: canvasReturnValue}
      log.info(document)
      return document
    })
 }

 module.exports = function (msg, counter) {
   log.info('Processing for msg..... ' + msg.ug1Name)
   var msgtype = msg._desc.userType
   if (msg._desc && (msgtype === type.students || msgtype === type.omregistrerade || msgtype === type.teachers || msgtype === type.assistants || msgtype === type.courseresponsibles)) {
     return _process(msg)
   } else {
     log.error('This is something else than students, teacher, assistant, courseresponsibles we can probably wait with this until the students is handled', JSON.stringify(msg, null, 4))
     return Promise.resolve('Unknown flag: ' + msgtype)
   }
 }
<commit_msg>no default value for sisCourseCode<commit_after> 'use strict'

 const {type} = require('message-type')
 const canvasApi = require('../canvasApi')
 const Promise = require('bluebird')
 const config = require('../server/init/configuration')
 const log = require('../server/init/logging')
 const ugParser = require('./ugParser')
 const calcSisForOmregistrerade = require('./calcSisForOmregistrerade')
 require('colors')
 const createCsvFile = require('./createCsvFile')
 const csvVol = config.full.azure.csvBlobName
 const csvDir = config.full.localFile.csvDir

 function _parseKey (msg) {
   console.log('msg', msg)
   const {ug1Name, _desc} = msg
   const {userType} = _desc

   if (userType === type.students) {
     return Promise.resolve(ugParser.parseKeyStudent(ug1Name))
   }

   if (userType === type.teachers || userType === type.assistants || userType === type.courseresponsibles) {
     return Promise.resolve(ugParser.parseKeyTeacher(ug1Name))
   }

   log.error('Course code not parsable from Key. type, ', userType + ' ug1Name, ' + ug1Name)
   return Promise.reject(Error('Key parse error, type, ' + userType + ' ug1Name, ' + ug1Name))
 }

 function _process (msg) {
   let sisCourseCode
   let sisCourseCodeFunction
   if (msg._desc.userType === type.omregistrerade) {
     log.info('using calcSisForOmregistrerade')
     sisCourseCodeFunction = calcSisForOmregistrerade
   } else {
     log.info('using _parseKey')
     sisCourseCodeFunction = _parseKey
   }

   return sisCourseCodeFunction(msg)
    .then(_sisCourseCode => { sisCourseCode = _sisCourseCode })
    .then(() => createCsvFile(msg, sisCourseCode, csvDir, csvVol))
    .then(csvObject => {
      log.info('FileName: ', csvObject.csvFileName)
      return csvObject.csvFileName
    })
    .then(fileName => canvasApi.sendCsvFile(fileName, true))
    .then(canvasReturnValue => {
      let document = {msg: msg, resp: canvasReturnValue}
      log.info(document)
      return document
    })
 }

 module.exports = function (msg, counter) {
   log.info('Processing for msg..... ' + msg.ug1Name)
   var msgtype = msg._desc.userType
   if (msg._desc && (msgtype === type.students || msgtype === type.omregistrerade || msgtype === type.teachers || msgtype === type.assistants || msgtype === type.courseresponsibles)) {
     return _process(msg)
   } else {
     log.error('This is something else than students, teacher, assistant, courseresponsibles we can probably wait with this until the students is handled', JSON.stringify(msg, null, 4))
     return Promise.resolve('Unknown flag: ' + msgtype)
   }
 }
<|endoftext|>


<commit_before>window.Aeria = window.Aeria || {};
Aeria.social = (function(){
	var self = {};
	var $ = jQuery;

	function getAjaxCount(data, callback) {
		if (window.AERIA_SOCIAL && window.AERIA_SOCIAL.URL != null) {
			$.getJSON(window.AERIA_SOCIAL.URL, data, function(response) {
				if (response == null) return;
				callback(response);
			});
		} else {
			Aeria.ajax.action('aeriasocial.get', data, function(response) {
				if (response == null) return;
				callback($.parseJSON(response) || {});
			});
		}
	}

	function setSum($t) {
		if ($t.data('aeriasocial-summed') == true) return;
		$t.attr('data-aeriasocial-summed', true);

		var sum = 0;
		$t.find('[data-aeriasocial-count]').each(function() {
			sum += ($(this).text() << 0);
		});

		var $cont = $t.parents('.aeriasocial-container');
		if ($cont.length > 0) {
			$cont.addClass('enabled');

			var $sum = $cont.find('[data-aeriasocial-count-sum]');
			if ($sum.length > 0) {
				$sum.addClass('enabled').text(sum + ' shares');
			}
		}
	}

	function popup($t) {
		var $p = $t.parents('[data-aeriasocial-uri]');

		var uri = $p.length > 0 ? encodeURIComponent($p.data('aeriasocial-uri')) : location.href;
		var service = $t.data('aeriasocial-service');
		var text = encodeURIComponent($t.data('aeriasocial-text')) || '';

		if (service === 'facebook') {
			popupJS('http://facebook.com/sharer/sharer.php?u=' + uri);
		} else if (service === 'twitter') {
			var via = encodeURIComponent($t.data('aeriasocial-via')) || '';
			popupJS('https://twitter.com/intent/tweet?url=' + uri + '&text=' + text + '&via=' + via);
		} else if (service === 'linkedin') {
			popupJS('http://www.linkedin.com/shareArticle?mini=true&url=' + uri);
		} else if (service === 'gplus') {
			popupJS('https://plus.google.com/share?url=' + uri);
		}
	}

	function popupJS(uri){
		var w = 550, h = 420, l = Math.floor((screen.width-w)/2), t = Math.floor((screen.height-h)/2);
		window.open(uri, '_blank', "width=" + w + ",height=" + h + ",top=" + t + ",left=" + l);
	}

	self.load = function() {
		var uri = [];

		$('[data-aeriasocial-needajax=true]').each(function(){
			var $t = $(this);
			if ($t.data('aeriasocial-needajax') == false) return;

			$t.attr('data-aeriasocial-needajax', false);
			$t.attr('data-aeriasocial-summed', false);
			uri.push( $t.data('aeriasocial-uri') );
		});

		if (uri.length === 0) return;

		getAjaxCount({
			uri: uri,
		}, function(response) {
			if ( ! $.isArray(response)) response = [ response ];

			$.each(response, function(key, response_per_uri) {
				var $t = $('[data-aeriasocial-uri="' + response_per_uri.uri + '"]');

				$.each(response_per_uri.services, function(srv, count) {
					$t.find('[data-aeriasocial-service="' + srv + '"] [data-aeriasocial-count]').html(count);
				});

				setSum($t);
			});

		});
	},

	self.bind = function() {
		$('[data-aeriasocial-uri]').each(function() {
			setSum( $(this) );
		});

		if (self.binded === true) return;
		self.binded = true;

		var st = (document.body || document.documentElement).style;
		if (st.transition==null && st.WebkitTransition==null && st.MozTransition==null && st.MsTransition==null && st.OTransition==null) {
			$(document.body).addClass('no-csstransforms');
		}

		if ('ontouchstart' in window) {
			$(document.body).on('touchstart', '.aeriasocial-container', function(){
				var $t = $(this);
				if ($t.hasClass('hover')) {
					return $t.removeClass('hover');
				}

				$('.aeriasocial-container.hover').removeClass('hover');
				$t.addClass('hover');
			});
		}

		$(document).on('click', '.aeriasocial-btn', function(e){
			e.preventDefault();
			e.stopPropagation();
			popup( $(this) );
		});
	};

	$(document).ready(function(){
		self.bind();
		self.load();
	});

	return self;

})();
<commit_msg>Update aeria.social.js<commit_after>window.Aeria = window.Aeria || {};
Aeria.social = (function(){
	var self = {};
	var $ = jQuery;

	function getAjaxCount(data, callback) {
		if (window.AERIA_SOCIAL && window.AERIA_SOCIAL.URL != null) {
			$.getJSON(window.AERIA_SOCIAL.URL, data, function(response) {
				if (response == null) return;
				callback(response);
			});
		} else {
			Aeria.ajax.action('aeriasocial.get', data, function(response) {
				if (response == null) return;
				callback($.parseJSON(response) || {});
			});
		}
	}

	function setSum($t) {
		if ($t.data('aeriasocial-summed') == true) return;
		$t.attr('data-aeriasocial-summed', true);

		var sum = 0;
		$t.find('[data-aeriasocial-count]').each(function() {
			sum += ($(this).text() << 0);
		});

		var $cont = $t.parents('.aeriasocial-container');
		if ($cont.length > 0) {
			$cont.addClass('enabled');

			var $sum = $cont.find('[data-aeriasocial-count-sum]');
			if ($sum.length > 0) {
				$sum.addClass('enabled').text(sum + ' shares');
			}
		}
	}

	function popup($t) {
		var service = $t.data('aeriasocial-service');

		var $p = $t.parents('[data-aeriasocial-uri]');
		var uri = ($p.length > 0 && $p.data('aeriasocial-uri')) ? encodeURIComponent($p.data('aeriasocial-uri')) : location.href;
		var text = $t.data('aeriasocial-text') ? encodeURIComponent($t.data('aeriasocial-text')) : document.title;

		if (service === 'facebook') {
			popupJS('http://facebook.com/sharer/sharer.php?u=' + uri);
		} else if (service === 'twitter') {
			popupJS('https://twitter.com/intent/tweet?url=' + uri + '&text=' + text + ($t.data('aeriasocial-via') ? '&via=' + encodeURIComponent($t.data('aeriasocial-via')) : '') );
		} else if (service === 'linkedin') {
			popupJS('http://www.linkedin.com/shareArticle?mini=true&url=' + uri);
		} else if (service === 'gplus') {
			popupJS('https://plus.google.com/share?url=' + uri);
		}
	}

	function popupJS(uri){
		var w = 550, h = 420, l = Math.floor((screen.width-w)/2), t = Math.floor((screen.height-h)/2);
		window.open(uri, '_blank', "width=" + w + ",height=" + h + ",top=" + t + ",left=" + l);
	}

	self.load = function() {
		var uri = [];

		$('[data-aeriasocial-needajax=true]').each(function(){
			var $t = $(this);
			if ($t.data('aeriasocial-needajax') == false) return;

			$t.attr('data-aeriasocial-needajax', false);
			$t.attr('data-aeriasocial-summed', false);
			uri.push( $t.data('aeriasocial-uri') );
		});

		if (uri.length === 0) return;

		getAjaxCount({
			uri: uri,
		}, function(response) {
			if ( ! $.isArray(response)) response = [ response ];

			$.each(response, function(key, response_per_uri) {
				var $t = $('[data-aeriasocial-uri="' + response_per_uri.uri + '"]');

				$.each(response_per_uri.services, function(srv, count) {
					$t.find('[data-aeriasocial-service="' + srv + '"] [data-aeriasocial-count]').html(count);
				});

				setSum($t);
			});

		});
	},

	self.bind = function() {
		$('[data-aeriasocial-uri]').each(function() {
			setSum( $(this) );
		});

		if (self.binded === true) return;
		self.binded = true;

		var st = (document.body || document.documentElement).style;
		if (st.transition==null && st.WebkitTransition==null && st.MozTransition==null && st.MsTransition==null && st.OTransition==null) {
			$(document.body).addClass('no-csstransforms');
		}

		if ('ontouchstart' in window) {
			$(document.body).on('touchstart', '.aeriasocial-container', function(){
				var $t = $(this);
				if ($t.hasClass('hover')) {
					return $t.removeClass('hover');
				}

				$('.aeriasocial-container.hover').removeClass('hover');
				$t.addClass('hover');
			});
		}

		$(document).on('click', '.aeriasocial-btn', function(e){
			e.preventDefault();
			e.stopPropagation();
			popup( $(this) );
		});
	};

	$(document).ready(function(){
		self.bind();
		self.load();
	});

	return self;

})();
<|endoftext|>


<commit_before>steal('funcunit/qunit', 'funcunit/syn', 'jquerypp/event/swipe', function (QUnit, Syn) {

	module("jquerypp/swipe", {setup : function () {
		$("#qunit-test-area").html("")
		var div = $("
" +
			"
one
" +
			"
two
three

" +
			"
");

		div.appendTo($("#qunit-test-area"));
		var basicCss = {
			position : "absolute",
			border : "solid 1px black"
		}
		$("#outer").css(basicCss).css({top : "10px", left : "10px",
			zIndex : 1000, backgroundColor : "green", width : "200px", height : "200px"})
	}});

	test("swipe right event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeleft",function () {
				ok(false, "swipe left")
			}).bind("swiperight", function () {
				ok(true, "swiperight")
			});
		stop();
		Syn.drag({
			from : "20x20",
			to : "50x20",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("swipe left event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeleft",function () {
				ok(true, "swipe left")
			}).bind("swiperight", function () {
				ok(false, "swiperight")
			});
		stop();
		Syn.drag({
			from : "50x20",
			to : "20x20",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("swipe up event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeup",function () {
				ok(true, "swipe left")
			}).bind("swiperight",function () {
				ok(false, "swiperight")
			}).bind("swipedown", function () {
				ok(false, "swipedown")
			});
		stop();
		Syn.drag({
			from : "20x50",
			to : "20x20",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("swipe down event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeup",function () {
				ok(false, "swipe left")
			}).bind("swiperight",function () {
				ok(false, "swiperight")
			}).bind("swipedown", function () {
				ok(true, "swipedown")
			});
		stop();
		Syn.drag({
			from : "20x20",
			to : "20x50",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("#33: using swipe.max", function () {

		$.event.swipe.max = 75;
		$("#outer").bind("swipe", function () {
			ok(false, "Swipe shouldn't be called when dragged more than swipe.max");
		});
		stop();
		Syn.drag({
			from : "20x20",
			to : "20x96",
			duration : 100
		}, "outer", function () {
			ok(true, 'Done dragging');
			start();
		})

	})

})<commit_msg>update swipe left to fix test for ie9<commit_after>steal('funcunit/qunit', 'funcunit/syn', 'jquerypp/event/swipe', function (QUnit, Syn) {

	module("jquerypp/swipe", {setup : function () {
		$("#qunit-test-area").html("")
		var div = $("
" +
			"
one
" +
			"
two
three

" +
			"
");

		div.appendTo($("#qunit-test-area"));
		var basicCss = {
			position : "absolute",
			border : "solid 1px black"
		}
		$("#outer").css(basicCss).css({top : "10px", left : "10px",
			zIndex : 1000, backgroundColor : "green", width : "200px", height : "200px"})
	}});

	test("swipe right event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeleft",function () {
				ok(false, "swipe left")
			}).bind("swiperight", function () {
				ok(true, "swiperight")
			});
		stop();
		Syn.drag({
			from : "20x20",
			to : "50x20",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("swipe left event", 2, function () {
		var swipe = {};

		$("#outer").bind("swipe",function () {
			swipe.general = true;
		}).bind("swipeleft",function () {
			swipe.left = true;
		});

		stop();

		Syn.drag({
			from : "50x20",
			to : "20x20",
			duration : 100
		}, "outer", function () {
			start();
			ok(swipe.general, 'swipe')
			ok(swipe.left, "swipe left")
		})
	});

	test("swipe up event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeup",function () {
				ok(true, "swipe left")
			}).bind("swiperight",function () {
				ok(false, "swiperight")
			}).bind("swipedown", function () {
				ok(false, "swipedown")
			});
		stop();
		Syn.drag({
			from : "20x50",
			to : "20x20",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("swipe down event", 2, function () {

		$("#outer").bind("swipe",function () {
			ok(true, "swipe called");
		}).bind("swipeup",function () {
				ok(false, "swipe left")
			}).bind("swiperight",function () {
				ok(false, "swiperight")
			}).bind("swipedown", function () {
				ok(true, "swipedown")
			});
		stop();
		Syn.drag({
			from : "20x20",
			to : "20x50",
			duration : 100
		}, "outer", function () {
			start();
		})

	});

	test("#33: using swipe.max", function () {

		$.event.swipe.max = 75;
		$("#outer").bind("swipe", function () {
			ok(false, "Swipe shouldn't be called when dragged more than swipe.max");
		});
		stop();
		Syn.drag({
			from : "20x20",
			to : "20x96",
			duration : 100
		}, "outer", function () {
			ok(true, 'Done dragging');
			start();
		})

	})

})
<|endoftext|>


<commit_before>function requestData() {
    "use strict";
    var req = new XMLHttpRequest();
    req.open("GET", "/games", true);
    req.setRequestHeader("accept", "application/json");

    req.onload = function() {
        if (req.status >= 200 && req.status < 400){
            var gamesjson = req.responseText;
            var gamesData = JSON.parse(gamesjson);
            var gamesToHtml = "";
            var x = 0;

            for (var key in gamesData.games) {
                if (!gamesData.games.hasOwnProperty(key)) {
                    continue;
                }
                gamesToHtml += "
";
                var gameurl = "/#" + gamesData.games[x].id;
                var threadurl = gamesData.games[x].url;
                gamesToHtml +=  '' + gamesData.games[x].name + "	";
                gamesToHtml += '' + threadurl + "	";
                gamesToHtml += "" + '<button type="button" onclick="deleteGame(\'' + gamesData.games[x].id + '\');return false;" class="pure-button">Delete</button>' + "	";
                gamesToHtml += "
";
                x++;
            }

            document.getElementById("games").innerHTML = gamesToHtml;
        } else {
            console.log("Error. Status code " + req.status);
        }
    };

    req.send(null);
    locationHashChanged();
}

function locationHashChanged() {
    "use strict";
    if (window.location.hash != "") {
        var id = "" + window.location.hash;
        id = id.slice(1, id.length);
        showGame(id);
    }
}

function showCreateGame() {
    "use strict";
    $("#index").addClass("hidden");
    $("#creategame").removeClass("hidden");
}

function hideCreateGame() {
    "use strict";
    $("#creategame").addClass("hidden");
    $("#index").removeClass("hidden");
    window.location.hash = "";
}

function showGame(id) {
    "use strict";
    var req = new XMLHttpRequest();
    var url = "/game/" + id;
    req.open("GET", url, true);
    req.setRequestHeader("accept", "application/json");

    req.onload = function() {
        if (req.status >= 200 && req.status < 400){
            var gamejson = req.responseText;
            var gameData = JSON.parse(gamejson);
            var gameToHtml = "";

            document.getElementById("gameheader").innerHTML = gameData.game.name;

            gameToHtml += '' + gameData.game.url + "

";

            var hosts = [];

            for (var i = 0; i < gameData.hosts.length; i++) {
                hosts.push(gameData.hosts[i]);
            }

            gameToHtml += "Hosts
" + hosts.join(', ');

            var players = [];

            for (var i = 0; i < gameData.players.length; i++) {
                players.push(gameData.players[i].name);
            }

            var playerLinks = [];

            for (var i = 0; i < gameData.players.length; i++) {
                playerLinks.push('' + gameData.players[i].name + '');
            }

            gameToHtml += "

Players
" + playerLinks.join(', ');

            gameToHtml += "
Click on a player to permanently remove him from the game!
";

            gameToHtml += '
Add Player
<form id="AddPlayerForm">Name: <input type="text" id="newPlayer"> <input type="button" class="pure-button" onclick="addPlayer(\'' + id + '\')" value="Add"></form>'

            var nicknames = getNicknames();

            var currentDay = 0;

            if (gameData.votes.length > 0) {
                currentDay = gameData.votes[gameData.votes.length - 1].day;

                var targets = [];

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay == gameData.votes[i].day) {
                        gameData.votes[i].target = gameData.votes[i].target.toLowerCase();
                        for (var key in nicknames) {
                            if (!nicknames.hasOwnProperty(key)) {
                                continue;
                            }
                            var nicknameslist = nicknames[key];
                            for (var j = 0; j < nicknameslist.length; j++) {
                                if (nicknameslist[j].toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                    // if a vote target equals one of the nicknames, then change the vote to target the "real" name
                                    gameData.votes[i].target = key;
                                }
                                if (key.toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                    // if a vote target equals a name with the wrong capitalization, then change the vote to target the "real" name                                         // (if it's in the nicknames list)
                                    gameData.votes[i].target = key;
                                }
                            }
                        }
                        for (var j = 0; j < players.length; j++) {
                            if (players[j].toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                // if a vote target equals a name with the wrong capitalization, then change the vote to target the "real" name                                         // (if it's in the players list)
                                gameData.votes[i].target = players[j];
                            }
                        }
                        if (players.length > 1 && gameData.votes[i].target.length > 1) {
                            // here we use the FuzzySet.js library to get the "most correct" vote
                            // target from the players list if the target is misspelled
                            var fuzzySet = FuzzySet(players);
                            var fuzzyResults = fuzzySet.get(gameData.votes[i].target.toLowerCase());
                            var fuzzyResult = fuzzyResults[0][1]; // first ("top") result, then the name (second value in the result array)
                            if (fuzzyResult != null) {
                                gameData.votes[i].target = fuzzyResult;
                            }
                            console.log(fuzzyResults);
                        }
                        if (targets.indexOf(gameData.votes[i].target) == -1) {
                            // push every new unique vote target to the targets array
                            targets.push(gameData.votes[i].target);
                        }
                }
                }

                for (var i = targets.length - 1; i >= 0; i--) {
                    if (targets[i] == "") {
                        // remove the null (unvote) target from the list of vote targets
                        targets.splice(i, 1);
                        break;
                    }
                }

                var voters = {}; // "voters" is a JavaScript object with targets as keys and their voters as values
                var activeVoters = {}; // "activeVoters" is a JavaScript object with targets as keys and ACTIVE (not unvoted) voters as values
                var nonvoters = players; // players who aren't voting for anyone at the current time

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay = gameData.votes[i].day) {
                        for (var j = 0; j < targets.length; j++) {
                            if (gameData.votes[i].target.toLowerCase() == targets[j].toLowerCase()) {
                                if(voters.hasOwnProperty(targets[j]) || activeVoters.hasOwnProperty(targets[j])){
                                    continue;
                                }
                                // add a new key (property) to the object for every vote target during the current day
                                voters[targets[j]] = [];
                                activeVoters[targets[j]] = [];
                            }
                        }
                    }
                }

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay == gameData.votes[i].day) {
                        for (var j = 0; j < targets.length; j++) {
                            var remainingVoters = activeVoters[targets[j]].slice(0);
                            for (var z = remainingVoters.length - 1; z >= 0; z--) {
                                if (remainingVoters[z] == gameData.votes[i].voter) {
                                    // every time a new vote is given, remove every previous vote from the active votes
                                    remainingVoters.splice(z, 1);
                                }
                            }
                            var markedVoters = voters[targets[j]].slice(0);
                            for (var z = markedVoters.length - 1; z >= 0; z--) {
                                if (markedVoters[z] == gameData.votes[i].voter) {
                                    // every time a new vote is given, mark every previous vote with the mark "!" (unvoted) in the general votes
                                    markedVoters[z] = "!" + markedVoters[z];
                                }
                            }
                            activeVoters[targets[j]] = remainingVoters;
                            voters[targets[j]] = markedVoters;
                            if (gameData.votes[i].target.toLowerCase() == targets[j].toLowerCase() && gameData.votes[i].target != "") {
                                // push every voter of the current day to the objects as a value of their vote target
                                voters[targets[j]].push(gameData.votes[i].voter);
                                activeVoters[targets[j]].push(gameData.votes[i].voter);
                            }
                        }
                    }
                }

                for (var i = 0; i < targets.length; i++) {
                    var activesList = activeVoters[targets[i]];
                    for (var j = 0; j < activesList.length; j++) {
                        for (var z = nonvoters.length - 1; z >= 0; z--) {
                            if (activesList[j] == nonvoters[z]) {
                                // remove every currently active voter from the "Not Voting" list
                                nonvoters.splice(z, 1);
                            }
                        }
                    }
                }

                var sortedTargets = sort(activeVoters);

                gameToHtml += "

Day " + currentDay + " Votecount
";

                for (var target in sortedTargets) {
                	if (sortedTargets.hasOwnProperty(target)) {
                		var mainVotersList = voters[target].slice(0);
                		for (var i = 0; i<mainVotersList.length; i++) {
                			if (mainVotersList[i].indexOf("!") != -1) {
                				var nameWithoutMark = mainVotersList[i].substring(1);
                				mainVotersList[i] = "<s>" + nameWithoutMark + "</s>";
                			}
                		}
                	}

                	gameToHtml += "
" + target + " (" + sortedTargets[target].length + "): " + mainVotersList.join(', ');
                }

                gameToHtml += '

Not Voting (' + nonvoters.length + '): ' + nonvoters.join(', ');
            }

            var firstNewDayVote = false;
            currentDay = 0;

            for (var i = 0; i < gameData.votes.length; i++) {
                var post = gameData.votes[i].index;
                var page = Math.floor(post/20) + 1;
                var address = gameData.game.url + "?page=" + page + "#" + post;

                if (currentDay != gameData.votes[i].day) {
                    firstNewDayVote = true;
                    currentDay = gameData.votes[i].day;
                }
                if (firstNewDayVote === true) {
                    gameToHtml += "

Day " + gameData.votes[i].day + "
";
                    firstNewDayVote = false;
                }
                if (gameData.votes[i].target == "") {
                    gameToHtml += '
' + gameData.votes[i].voter + " unvoted";
                } else if (gameData.votes[i].target == null) {
                    gameToHtml += '
' + gameData.votes[i].voter + " gave an invalid vote!";
                } else {
                    gameToHtml += '
' + gameData.votes[i].voter +
                        " voted for " + gameData.votes[i].target + "";
                }
            }

            if (gameData.votes.length > 0) {
                gameToHtml += '

<textarea id="reply_area" cols=80 rows=25 name="bericht" style="font:10pt Arial; margin-bottom: 4px; width:732px">';
                currentDay = gameData.votes[gameData.votes.length - 1].day;

                gameToHtml += "[blue][b][u][big]Day " + currentDay + " Votecount[/big][/u][/b][/blue]\r\n\r\n";

                for (var target in sortedTargets) {
                	if (sortedTargets.hasOwnProperty(target)) {
                		var mainVotersList = voters[target].slice(0);
                		for (var i = 0; i<mainVotersList.length; i++) {
                			if (mainVotersList[i].indexOf("!") != -1) {
                				var nameWithoutMark = mainVotersList[i].substring(1);
                				mainVotersList[i] = "[s]" + nameWithoutMark + "[/s]";
                			}
                		}
                	}

                	gameToHtml += "[b]" + target + " (" + sortedTargets[target].length + "):[/b] " + mainVotersList.join(', ') + "\r\n";
                }

                gameToHtml += '\r\n' + '[b]Not Voting (' + nonvoters.length + '):[/b] ' + nonvoters.join(', ');
                gameToHtml += '</textarea>';
            }

            if (gameData.votes.length === 0) {
                gameToHtml += "
No votes have been extracted from the given thread yet (this may take more time or there may have been an error while reading the thread)
";
            }

            document.getElementById("gamedata").innerHTML = gameToHtml;
        } else {
            console.log("Error. Status code " + req.status);
        }
    };

    req.send(null);
    $("#index").addClass("hidden");
    $("#gameview").removeClass("hidden");
}

function deletePlayer(id) {
    "use strict";
    $.post("/delete-player", {id: id});
    locationHashChanged();
}

function deleteGame(id) {
    "use strict";
    $.post("/delete-game", {id: id});
    requestData();
}

function hideGame() {
    "use strict";
    $("#gameview").addClass("hidden");
    $("#index").removeClass("hidden");
    window.location.hash = "";
}

function addPlayer(gameid) {
	"use strict";
	if (document.getElementById("newPlayer").value) {
		var player = {"game": gameid, "name": document.getElementById("newPlayer").value}
		$.post("/add-player", player);
        locationHashChanged();
	}
}

function sort(activeVoters) {
	var targetLengthObjects = [];
    for (var target in activeVoters) {
        if (activeVoters.hasOwnProperty(target)) {
            targetLengthObjects.push({
                'key': target,
                'value': activeVoters[target].length
            });
        }
    }
    targetLengthObjects.sort(function(a, b) { return b.value - a.value; });
    var sorted = {};

    for (var i = 0; i < targetLengthObjects.length; i++) {
    	sorted[targetLengthObjects[i].key] = activeVoters[targetLengthObjects[i].key];
    }
	return sorted;
}

requestData();<commit_msg>now the fuzzy matching should be working and finished<commit_after>function requestData() {
    "use strict";
    var req = new XMLHttpRequest();
    req.open("GET", "/games", true);
    req.setRequestHeader("accept", "application/json");

    req.onload = function() {
        if (req.status >= 200 && req.status < 400){
            var gamesjson = req.responseText;
            var gamesData = JSON.parse(gamesjson);
            var gamesToHtml = "";
            var x = 0;

            for (var key in gamesData.games) {
                if (!gamesData.games.hasOwnProperty(key)) {
                    continue;
                }
                gamesToHtml += "
";
                var gameurl = "/#" + gamesData.games[x].id;
                var threadurl = gamesData.games[x].url;
                gamesToHtml +=  '' + gamesData.games[x].name + "	";
                gamesToHtml += '' + threadurl + "	";
                gamesToHtml += "" + '<button type="button" onclick="deleteGame(\'' + gamesData.games[x].id + '\');return false;" class="pure-button">Delete</button>' + "	";
                gamesToHtml += "
";
                x++;
            }

            document.getElementById("games").innerHTML = gamesToHtml;
        } else {
            console.log("Error. Status code " + req.status);
        }
    };

    req.send(null);
    locationHashChanged();
}

function locationHashChanged() {
    "use strict";
    if (window.location.hash != "") {
        var id = "" + window.location.hash;
        id = id.slice(1, id.length);
        showGame(id);
    }
}

function showCreateGame() {
    "use strict";
    $("#index").addClass("hidden");
    $("#creategame").removeClass("hidden");
}

function hideCreateGame() {
    "use strict";
    $("#creategame").addClass("hidden");
    $("#index").removeClass("hidden");
    window.location.hash = "";
}

function showGame(id) {
    "use strict";
    var req = new XMLHttpRequest();
    var url = "/game/" + id;
    req.open("GET", url, true);
    req.setRequestHeader("accept", "application/json");

    req.onload = function() {
        if (req.status >= 200 && req.status < 400){
            var gamejson = req.responseText;
            var gameData = JSON.parse(gamejson);
            var gameToHtml = "";

            document.getElementById("gameheader").innerHTML = gameData.game.name;

            gameToHtml += '' + gameData.game.url + "

";

            var hosts = [];

            for (var i = 0; i < gameData.hosts.length; i++) {
                hosts.push(gameData.hosts[i]);
            }

            gameToHtml += "Hosts
" + hosts.join(', ');

            var players = [];

            for (var i = 0; i < gameData.players.length; i++) {
                players.push(gameData.players[i].name);
            }

            var playerLinks = [];

            for (var i = 0; i < gameData.players.length; i++) {
                playerLinks.push('' + gameData.players[i].name + '');
            }

            gameToHtml += "

Players
" + playerLinks.join(', ');

            gameToHtml += "
Click on a player to permanently remove him from the game!
";

            gameToHtml += '
Add Player
<form id="AddPlayerForm">Name: <input type="text" id="newPlayer"> <input type="button" class="pure-button" onclick="addPlayer(\'' + id + '\')" value="Add"></form>'

            var nicknames = getNicknames();

            var currentDay = 0;

            if (gameData.votes.length > 0) {
                currentDay = gameData.votes[gameData.votes.length - 1].day;

                var targets = [];

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay == gameData.votes[i].day) {
                        gameData.votes[i].target = gameData.votes[i].target.toLowerCase();
                        for (var key in nicknames) {
                            if (!nicknames.hasOwnProperty(key)) {
                                continue;
                            }
                            var nicknameslist = nicknames[key];
                            for (var j = 0; j < nicknameslist.length; j++) {
                                if (nicknameslist[j].toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                    // if a vote target equals one of the nicknames, then change the vote to target the "real" name
                                    gameData.votes[i].target = key;
                                }
                                if (key.toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                    // if a vote target equals a name with the wrong capitalization, then change the vote to target the "real" name                                         // (if it's in the nicknames list)
                                    gameData.votes[i].target = key;
                                }
                            }
                        }
                        for (var j = 0; j < players.length; j++) {
                            if (players[j].toLowerCase() == gameData.votes[i].target.toLowerCase()) {
                                // if a vote target equals a name with the wrong capitalization, then change the vote to target the "real" name                                         // (if it's in the players list)
                                gameData.votes[i].target = players[j];
                            }
                        }
                        if (players.length > 1 && gameData.votes[i].target.length > 1) {
                            // here we use the FuzzySet.js library to get the "most correct" vote
                            // target from the players list if the target is misspelled
                            var fuzzySet = FuzzySet(players);
                            var fuzzyResults = fuzzySet.get(gameData.votes[i].target.toLowerCase());
                            if (fuzzyResults.length > 0) {
                                var fuzzyResult = fuzzyResults[0][1]; // first ("top") result, then the name (second value in the result array)
                                gameData.votes[i].target = fuzzyResult;
                            }
                        }
                        if (targets.indexOf(gameData.votes[i].target) == -1) {
                            // push every new unique vote target to the targets array
                            targets.push(gameData.votes[i].target);
                        }
                }
                }

                for (var i = targets.length - 1; i >= 0; i--) {
                    if (targets[i] == "") {
                        // remove the null (unvote) target from the list of vote targets
                        targets.splice(i, 1);
                        break;
                    }
                }

                var voters = {}; // "voters" is a JavaScript object with targets as keys and their voters as values
                var activeVoters = {}; // "activeVoters" is a JavaScript object with targets as keys and ACTIVE (not unvoted) voters as values
                var nonvoters = players; // players who aren't voting for anyone at the current time

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay = gameData.votes[i].day) {
                        for (var j = 0; j < targets.length; j++) {
                            if (gameData.votes[i].target.toLowerCase() == targets[j].toLowerCase()) {
                                if(voters.hasOwnProperty(targets[j]) || activeVoters.hasOwnProperty(targets[j])){
                                    continue;
                                }
                                // add a new key (property) to the object for every vote target during the current day
                                voters[targets[j]] = [];
                                activeVoters[targets[j]] = [];
                            }
                        }
                    }
                }

                for (var i = 0; i < gameData.votes.length; i++) {
                    if (currentDay == gameData.votes[i].day) {
                        for (var j = 0; j < targets.length; j++) {
                            var remainingVoters = activeVoters[targets[j]].slice(0);
                            for (var z = remainingVoters.length - 1; z >= 0; z--) {
                                if (remainingVoters[z] == gameData.votes[i].voter) {
                                    // every time a new vote is given, remove every previous vote from the active votes
                                    remainingVoters.splice(z, 1);
                                }
                            }
                            var markedVoters = voters[targets[j]].slice(0);
                            for (var z = markedVoters.length - 1; z >= 0; z--) {
                                if (markedVoters[z] == gameData.votes[i].voter) {
                                    // every time a new vote is given, mark every previous vote with the mark "!" (unvoted) in the general votes
                                    markedVoters[z] = "!" + markedVoters[z];
                                }
                            }
                            activeVoters[targets[j]] = remainingVoters;
                            voters[targets[j]] = markedVoters;
                            if (gameData.votes[i].target.toLowerCase() == targets[j].toLowerCase() && gameData.votes[i].target != "") {
                                // push every voter of the current day to the objects as a value of their vote target
                                voters[targets[j]].push(gameData.votes[i].voter);
                                activeVoters[targets[j]].push(gameData.votes[i].voter);
                            }
                        }
                    }
                }

                for (var i = 0; i < targets.length; i++) {
                    var activesList = activeVoters[targets[i]];
                    for (var j = 0; j < activesList.length; j++) {
                        for (var z = nonvoters.length - 1; z >= 0; z--) {
                            if (activesList[j] == nonvoters[z]) {
                                // remove every currently active voter from the "Not Voting" list
                                nonvoters.splice(z, 1);
                            }
                        }
                    }
                }

                var sortedTargets = sort(activeVoters);

                gameToHtml += "

Day " + currentDay + " Votecount
";

                for (var target in sortedTargets) {
                	if (sortedTargets.hasOwnProperty(target)) {
                		var mainVotersList = voters[target].slice(0);
                		for (var i = 0; i<mainVotersList.length; i++) {
                			if (mainVotersList[i].indexOf("!") != -1) {
                				var nameWithoutMark = mainVotersList[i].substring(1);
                				mainVotersList[i] = "<s>" + nameWithoutMark + "</s>";
                			}
                		}
                	}

                	gameToHtml += "
" + target + " (" + sortedTargets[target].length + "): " + mainVotersList.join(', ');
                }

                gameToHtml += '

Not Voting (' + nonvoters.length + '): ' + nonvoters.join(', ');
            }

            var firstNewDayVote = false;
            currentDay = 0;

            for (var i = 0; i < gameData.votes.length; i++) {
                var post = gameData.votes[i].index;
                var page = Math.floor(post/20) + 1;
                var address = gameData.game.url + "?page=" + page + "#" + post;

                if (currentDay != gameData.votes[i].day) {
                    firstNewDayVote = true;
                    currentDay = gameData.votes[i].day;
                }
                if (firstNewDayVote === true) {
                    gameToHtml += "

Day " + gameData.votes[i].day + "
";
                    firstNewDayVote = false;
                }
                if (gameData.votes[i].target == "") {
                    gameToHtml += '
' + gameData.votes[i].voter + " unvoted";
                } else if (gameData.votes[i].target == null) {
                    gameToHtml += '
' + gameData.votes[i].voter + " gave an invalid vote!";
                } else {
                    gameToHtml += '
' + gameData.votes[i].voter +
                        " voted for " + gameData.votes[i].target + "";
                }
            }

            if (gameData.votes.length > 0) {
                gameToHtml += '

<textarea id="reply_area" cols=80 rows=25 name="bericht" style="font:10pt Arial; margin-bottom: 4px; width:732px">';
                currentDay = gameData.votes[gameData.votes.length - 1].day;

                gameToHtml += "[blue][b][u][big]Day " + currentDay + " Votecount[/big][/u][/b][/blue]\r\n\r\n";

                for (var target in sortedTargets) {
                	if (sortedTargets.hasOwnProperty(target)) {
                		var mainVotersList = voters[target].slice(0);
                		for (var i = 0; i<mainVotersList.length; i++) {
                			if (mainVotersList[i].indexOf("!") != -1) {
                				var nameWithoutMark = mainVotersList[i].substring(1);
                				mainVotersList[i] = "[s]" + nameWithoutMark + "[/s]";
                			}
                		}
                	}

                	gameToHtml += "[b]" + target + " (" + sortedTargets[target].length + "):[/b] " + mainVotersList.join(', ') + "\r\n";
                }

                gameToHtml += '\r\n' + '[b]Not Voting (' + nonvoters.length + '):[/b] ' + nonvoters.join(', ');
                gameToHtml += '</textarea>';
            }

            if (gameData.votes.length === 0) {
                gameToHtml += "
No votes have been extracted from the given thread yet (this may take more time or there may have been an error while reading the thread)
";
            }

            document.getElementById("gamedata").innerHTML = gameToHtml;
        } else {
            console.log("Error. Status code " + req.status);
        }
    };

    req.send(null);
    $("#index").addClass("hidden");
    $("#gameview").removeClass("hidden");
}

function deletePlayer(id) {
    "use strict";
    $.post("/delete-player", {id: id});
    locationHashChanged();
}

function deleteGame(id) {
    "use strict";
    $.post("/delete-game", {id: id});
    requestData();
}

function hideGame() {
    "use strict";
    $("#gameview").addClass("hidden");
    $("#index").removeClass("hidden");
    window.location.hash = "";
}

function addPlayer(gameid) {
	"use strict";
	if (document.getElementById("newPlayer").value) {
		var player = {"game": gameid, "name": document.getElementById("newPlayer").value}
		$.post("/add-player", player);
        locationHashChanged();
	}
}

function sort(activeVoters) {
	var targetLengthObjects = [];
    for (var target in activeVoters) {
        if (activeVoters.hasOwnProperty(target)) {
            targetLengthObjects.push({
                'key': target,
                'value': activeVoters[target].length
            });
        }
    }
    targetLengthObjects.sort(function(a, b) { return b.value - a.value; });
    var sorted = {};

    for (var i = 0; i < targetLengthObjects.length; i++) {
    	sorted[targetLengthObjects[i].key] = activeVoters[targetLengthObjects[i].key];
    }
	return sorted;
}

requestData();<|endoftext|>


<commit_before>
  command: 'curl -s "http://legacy.cafebonappetit.com/api/2/menus?cafe=261"',
  refreshFrequency: 300000,

  render: function(output) {
    return [
        '

',
        '

',
        '<select class="myDiet">',
        '  <option value="-1">All</option>',
        '  <option value="6">Farm to Fork</option>',
        '  <option value="18">Humane</option>',
        '  <option value="7">In-Balance</option>',
        '  <option value="9">Made Without Gluten</option>',
        '  <option value="57">Contains Nuts</option>',
        '  <option value="3">Seafood Watch</option>',
        '  <option value="1">Vegetarian</option>',
        '  <option value="4">Vegan</option>',
        '</select>',
        '
',
        '

',
        '

',
    ].join('')
  },

  update: function(output, domEl) {

    var dietSelection = document.querySelector(".myDiet");
    dietSelection.onchange = function() {
        // save to LocalStorage every time we make a change
        saveSettings(dietSelection.value);
    };

    function saveSettings(diet) {
        var userSettings = {
            diet: diet,
        };

        localStorage.setItem('BonAppSettings', JSON.stringify(userSettings));

        var friendly = parseMenu(theMenu, diet);
        outputString = createOutputString(friendly);
        updateView();

        return;
    }

    function createOutputString(okItems){
        var str = "";
        for(var i = 0; i < okItems.length; i++){
            str += okItems[i] + "
";
        }
        return str;
    }

    function parseDate(x){
        var m,d,y;
        y=x.substr(0,4);
        m=x.substr(5,2);
        d=x.substr(8,2);

        var rawToday = new Date(y+"-"+m+"-"+d);
        var offsetDate = Date(rawToday - rawToday.getTimezoneOffset());
        var todayDate = new Date(offsetDate).toString();
        var today = todayDate.substr(0,10);

        return today.toString();
    }

    function parseCafe(json) {
        var id = ([Object.keys(json["days"][0]["cafes"])[0]]);
        var theTitle = json["days"][0]["cafes"][id]["name"];
        return theTitle;
    }

    function parseMenu(menu, diet){
        // your selected diets
        var preferredDiet = parseInt(diet);

        var okItems = [];
        var prevStation = "";
        var item = "";

        for(var prop in menu){
            // looping through the properties on an element
            if(menu.hasOwnProperty(prop)){
                    // Icon (filtering dietary restrictions)
                    if(menu[prop].cor_icon.hasOwnProperty(preferredDiet) || preferredDiet == -1){
                        // Station
                        if(menu[prop].station != prevStation){
                            // clean station string
                            item = "
" + cleanUpStationLabel(menu[prop].station + "
");
                            // push food label next to the station
                            item += "⚬ " + capitalizeStr(menu[prop].label, 0, 1);
                            // the previous station
                            prevStation = menu[prop].station;
                        }
                        // same station with more items
                        else {
                            // the served food item
                            item = "⚬ " + capitalizeStr(menu[prop].label, 0, 1);
                            // the previous station
                            prevStation = menu[prop].station;
                        }
                        // add it
                        okItems.push(item);
                    }
            }
        }
        // Handle update on Mondays and 0 results
        if(okItems.length === 0) {
            // Body
            okItems.push("0 menu items found...");

            // Footer
            var theDay = new Date().getDay();
            if(theDay === 1) {
                var footer = document.getElementById("footer");
                footer.innerHTML = "*Note: the menu usually updates on Mondays";
            }
        }

        return okItems;
    }

    function lastUpdated() {
        var time    = new Date();
        var hours   = time.getHours();
        var minutes = time.getMinutes();
        var timeOfDay = "";

        // convert from military time
        if (hours > 12) {
            timeOfDay = "pm";
            hours -= 12;
        } else if (hours === 0) {
            timeOfDay = "am";
            hours = 12;
        } else {
            timeOfDay = "am";
        }

        var lastUpdated = "Updated at " + pad(hours) + ":" + pad(minutes) + timeOfDay;

        return lastUpdated;
    }

    function pad(number) {
        return (number < 10 ? '0' : '') + number;
    }

    function capitalizeStr(theStr, upperCaseLetter, removeLetter) {
        var newCapitalStr = theStr[upperCaseLetter].toUpperCase() + theStr.slice(removeLetter)
        return newCapitalStr;
    }

    function cleanUpStationLabel(theStation) {
        // replace the @ symbol
        var cleanString = theStation.replace("@", "");
        // capitalize first letter
        var capitalizedStr = capitalizeStr(cleanString, 8, 9);
        // add back in the bold formatting
        capitalizedStr = "" + capitalizedStr + "";

        return capitalizedStr;
    }

    function updateView() {
        //Output
        try {
            dom.find(widgetTitle).html(title);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(date).html(theDate);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(footerBA).html(lastUpdated);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(food).html(outputString);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
    }

    function initFromLocalStorage() {
        // check to see if LocalStorage has been set
        if (localStorage.getItem("BonAppSettings") != null) {
            var savedDiet = localStorage.getItem("BonAppSettings");
            var theValue = JSON.parse(savedDiet).diet;
            document.querySelector(".myDiet").value = theValue;
        }
        else {
            return -1;
        }

        return theValue;
    }

    var savedDiet = initFromLocalStorage();

    var dom,
     theDate,
     theMenu,
     title,
     lastUpdated,
     jstringObj,
     outputString;

    dom          = $(domEl);
    jstringObj   = JSON.parse(output);
    title        = parseCafe(jstringObj);
    lastUpdated  = lastUpdated();
    theDate      = parseDate(jstringObj.days[0].date);
    theMenu      = jstringObj.items;
    var friendly = parseMenu(theMenu, savedDiet);
    outputString = createOutputString(friendly);

    updateView();
  },

  style: [
    "top: 20px",
    "left: 40px",
    "width:400px",
    "margin:0px",
    "padding:0px",
    "background:rgba(#FFF, 0.5)",
    "border:2px solid rgba(#000, 0.5)",
    "border-radius:10px",
    "overflow:hidden",

    "#updated",
    "  font-family: Helvetica",
    "  font-size: 12pt",
    "  color: rgba(0,0,0,0.75)",

    "#date",
    "  text-align:center",
    "  margin-bottom:12pt",
    "  margin-top: -40px",
    "  font-family: Helvetica",
    "  font-size: 15pt",
    "  font-weight:bold",
    "  color: rgba(0,0,0,0.75)",

    "#widgetTitle",
    "  text-align:center",
    "  margin-top:12pt",
    "  margin-bottom:0pt",
    "  font-family: Helvetica",
    "  font-size: 25pt",
    "  font-weight:bold",
    "  color: rgba(128,0,0,0.75)",
    "  border-bottom: solid 1px black",

    "#description",
    "  margin-left:12pt",
    "  margin-right:12pt",
    "  font-family: American Typewriter",
    "  font-size: 12pt",
    "  line-height:18pt",
    "  max-height:10pt",
    "  overflow:hidden",
    "  hyphens: auto",

    "#food",
    "  margin-top: -60px",
    "  height: auto",
    "  margin-left: 20px",

    "#footerBA",
    "  text-align: center",
    "  font-family: Helvetica",
    "  font-size: 9pt",
    "  margin-top: 12pt",
    "  margin-bottom: 12pt",
    "  color: rgba(#000, 0.5)",

    "p",
    "  margin: 0 0 0 20px",

    "hr",
    "  margin-top: -20px",
    "  border-width: 1px",
    "  color: black",
    "  border-style: solid",

    "::-webkit-scrollbar",
    "  display: none",

    ".e",
    "  height: 60pt",

    ".event",
    "  font-size: 17pt",
    "  font-weight: bold",
    ].join('\n')
<commit_msg>Removed the message about updates on Mondays<commit_after>
  command: 'curl -s "http://legacy.cafebonappetit.com/api/2/menus?cafe=261"',
  refreshFrequency: 300000,

  render: function(output) {
    return [
        '

',
        '

',
        '<select class="myDiet">',
        '  <option value="-1">All</option>',
        '  <option value="6">Farm to Fork</option>',
        '  <option value="18">Humane</option>',
        '  <option value="7">In-Balance</option>',
        '  <option value="9">Made Without Gluten</option>',
        '  <option value="57">Contains Nuts</option>',
        '  <option value="3">Seafood Watch</option>',
        '  <option value="1">Vegetarian</option>',
        '  <option value="4">Vegan</option>',
        '</select>',
        '
',
        '

',
        '

',
    ].join('')
  },

  update: function(output, domEl) {

    var dietSelection = document.querySelector(".myDiet");
    dietSelection.onchange = function() {
        // save to LocalStorage every time we make a change
        saveSettings(dietSelection.value);
    };

    function saveSettings(diet) {
        var userSettings = {
            diet: diet,
        };

        localStorage.setItem('BonAppSettings', JSON.stringify(userSettings));

        var friendly = parseMenu(theMenu, diet);
        outputString = createOutputString(friendly);
        updateView();

        return;
    }

    function createOutputString(okItems){
        var str = "";
        for(var i = 0; i < okItems.length; i++){
            str += okItems[i] + "
";
        }
        return str;
    }

    function parseDate(x){
        var m,d,y;
        y=x.substr(0,4);
        m=x.substr(5,2);
        d=x.substr(8,2);

        var rawToday = new Date(y+"-"+m+"-"+d);
        var offsetDate = Date(rawToday - rawToday.getTimezoneOffset());
        var todayDate = new Date(offsetDate).toString();
        var today = todayDate.substr(0,10);

        return today.toString();
    }

    function parseCafe(json) {
        var id = ([Object.keys(json["days"][0]["cafes"])[0]]);
        var theTitle = json["days"][0]["cafes"][id]["name"];
        return theTitle;
    }

    function parseMenu(menu, diet){
        // your selected diets
        var preferredDiet = parseInt(diet);

        var okItems = [];
        var prevStation = "";
        var item = "";

        for(var prop in menu){
            // looping through the properties on an element
            if(menu.hasOwnProperty(prop)){
                    // Icon (filtering dietary restrictions)
                    if(menu[prop].cor_icon.hasOwnProperty(preferredDiet) || preferredDiet == -1){
                        // Station
                        if(menu[prop].station != prevStation){
                            // clean station string
                            item = "
" + cleanUpStationLabel(menu[prop].station + "
");
                            // push food label next to the station
                            item += "⚬ " + capitalizeStr(menu[prop].label, 0, 1);
                            // the previous station
                            prevStation = menu[prop].station;
                        }
                        // same station with more items
                        else {
                            // the served food item
                            item = "⚬ " + capitalizeStr(menu[prop].label, 0, 1);
                            // the previous station
                            prevStation = menu[prop].station;
                        }
                        // add it
                        okItems.push(item);
                    }
            }
        }
        // Handle update on Mondays and 0 results
        if(okItems.length === 0) {
            // Body
            okItems.push("0 menu items found...");
		}
        return okItems;
    }

    function lastUpdated() {
        var time    = new Date();
        var hours   = time.getHours();
        var minutes = time.getMinutes();
        var timeOfDay = "";

        // convert from military time
        if (hours > 12) {
            timeOfDay = "pm";
            hours -= 12;
        } else if (hours === 0) {
            timeOfDay = "am";
            hours = 12;
        } else {
            timeOfDay = "am";
        }

        var lastUpdated = "Updated at " + pad(hours) + ":" + pad(minutes) + timeOfDay;

        return lastUpdated;
    }

    function pad(number) {
        return (number < 10 ? '0' : '') + number;
    }

    function capitalizeStr(theStr, upperCaseLetter, removeLetter) {
        var newCapitalStr = theStr[upperCaseLetter].toUpperCase() + theStr.slice(removeLetter)
        return newCapitalStr;
    }

    function cleanUpStationLabel(theStation) {
        // replace the @ symbol
        var cleanString = theStation.replace("@", "");
        // capitalize first letter
        var capitalizedStr = capitalizeStr(cleanString, 8, 9);
        // add back in the bold formatting
        capitalizedStr = "" + capitalizedStr + "";

        return capitalizedStr;
    }

    function updateView() {
        //Output
        try {
            dom.find(widgetTitle).html(title);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(date).html(theDate);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(footerBA).html(lastUpdated);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
        try {
            dom.find(food).html(outputString);
        }
        catch(err) {
            console.log("Error: \"" + err.message + "\" on line " + err.line);
        }
    }

    function initFromLocalStorage() {
        // check to see if LocalStorage has been set
        if (localStorage.getItem("BonAppSettings") != null) {
            var savedDiet = localStorage.getItem("BonAppSettings");
            var theValue = JSON.parse(savedDiet).diet;
            document.querySelector(".myDiet").value = theValue;
        }
        else {
            return -1;
        }

        return theValue;
    }

    var savedDiet = initFromLocalStorage();

    var dom,
     theDate,
     theMenu,
     title,
     lastUpdated,
     jstringObj,
     outputString;

    dom          = $(domEl);
    jstringObj   = JSON.parse(output);
    title        = parseCafe(jstringObj);
    lastUpdated  = lastUpdated();
    theDate      = parseDate(jstringObj.days[0].date);
    theMenu      = jstringObj.items;
    var friendly = parseMenu(theMenu, savedDiet);
    outputString = createOutputString(friendly);

    updateView();
  },

  style: [
    "top: 20px",
    "left: 40px",
    "width:400px",
    "margin:0px",
    "padding:0px",
    "background:rgba(#FFF, 0.5)",
    "border:2px solid rgba(#000, 0.5)",
    "border-radius:10px",
    "overflow:hidden",

    "#updated",
    "  font-family: Helvetica",
    "  font-size: 12pt",
    "  color: rgba(0,0,0,0.75)",

    "#date",
    "  text-align:center",
    "  margin-bottom:12pt",
    "  margin-top: -40px",
    "  font-family: Helvetica",
    "  font-size: 15pt",
    "  font-weight:bold",
    "  color: rgba(0,0,0,0.75)",

    "#widgetTitle",
    "  text-align:center",
    "  margin-top:12pt",
    "  margin-bottom:0pt",
    "  font-family: Helvetica",
    "  font-size: 25pt",
    "  font-weight:bold",
    "  color: rgba(128,0,0,0.75)",
    "  border-bottom: solid 1px black",

    "#description",
    "  margin-left:12pt",
    "  margin-right:12pt",
    "  font-family: American Typewriter",
    "  font-size: 12pt",
    "  line-height:18pt",
    "  max-height:10pt",
    "  overflow:hidden",
    "  hyphens: auto",

    "#food",
    "  margin-top: -60px",
    "  height: auto",
    "  margin-left: 20px",

    "#footerBA",
    "  text-align: center",
    "  font-family: Helvetica",
    "  font-size: 9pt",
    "  margin-top: 12pt",
    "  margin-bottom: 12pt",
    "  color: rgba(#000, 0.5)",

    "p",
    "  margin: 0 0 0 20px",

    "hr",
    "  margin-top: -20px",
    "  border-width: 1px",
    "  color: black",
    "  border-style: solid",

    "::-webkit-scrollbar",
    "  display: none",

    ".e",
    "  height: 60pt",

    ".event",
    "  font-size: 17pt",
    "  font-weight: bold",
    ].join('\n')
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs-extra');
var path = require('path');
var logger = require('../util/logger');
var shell = require('shelljs');
var which = require('which');
var tar = require('tar');
var fstream = require('fstream');
var md5 = require('md5');
var tmp = require('tmp');
var _ = require('lodash');

var cacheVersion = '1';

function CacheDependencyManager (config) {
  this.config = config;
}

// Given a path relative to process' current working directory,
// returns a normalized absolute path
var getAbsolutePath = function (relativePath) {
  return path.resolve(process.cwd(), relativePath);
};

var getFileBackupPath = function (installedDirectory) {
  return path.join(installedDirectory, '.npm-cache');
};

var getFileBackupFilename = function (file) {
  return path.basename(file) + '_' + md5(file);
};

CacheDependencyManager.prototype.cacheLogInfo = function (message) {
  logger.logInfo('[' + this.config.cliName + '] ' + message);
};

CacheDependencyManager.prototype.cacheLogError = function (error) {
  logger.logError('[' + this.config.cliName + '] ' + error);
};

CacheDependencyManager.prototype.installDependencies = function () {
  var error = null;
  var installCommand = this.config.installCommand + ' ' + this.config.installOptions;
  installCommand = installCommand.trim();
  this.cacheLogInfo('running [' + installCommand + ']...');
  if (shell.exec(installCommand).code !== 0) {
    error = 'error running ' + this.config.installCommand;
    this.cacheLogError(error);
  } else {
    this.cacheLogInfo('installed ' + this.config.cliName + ' dependencies, now archiving');
  }
  return error;
};

CacheDependencyManager.prototype.backupFile = function (backupPath, file) {
  var sourceFile = getAbsolutePath(file);
  var backupFilename = getFileBackupFilename(file);
  var backupFile = path.join(backupPath, backupFilename);
  if (!fs.existsSync(sourceFile)) {
    this.cacheLogError('backup file [file not found]:' + file);
    return;
  }

  fs.mkdirsSync(backupPath);
  fs.copySync(sourceFile, backupFile);
  this.cacheLogInfo('backup file: ' + file);
};

CacheDependencyManager.prototype.restoreFile = function (backupPath, file) {
  var sourceFile = getAbsolutePath(file);
  var backupFilename = getFileBackupFilename(file);
  var backupFile = path.join(backupPath, backupFilename);
  if (!fs.existsSync(backupFile)) {
    this.cacheLogError('restore file [file not found]:' + file);
    return;
  }

  fs.copySync(backupFile, sourceFile);
  this.cacheLogInfo('restore file: ' + file);
};

CacheDependencyManager.prototype.archiveDependencies = function (cacheDirectory, cachePath, callback) {
  var self = this;
  var error = null;
  var installedDirectory = getAbsolutePath(this.config.installDirectory);
  var fileBackupDirectory = getFileBackupPath(installedDirectory);
  this.cacheLogInfo('archiving dependencies from ' + installedDirectory);

  if (!fs.existsSync(installedDirectory)) {
    this.cacheLogInfo('skipping archive. Install directory does not exist.');
    return error;
  }

  if (this.config.addToArchiveAndRestore) {
    this.backupFile(fileBackupDirectory, this.config.addToArchiveAndRestore);
  }

  // Make sure cache directory is created
  fs.mkdirsSync(cacheDirectory);

  var tmpName = tmp.tmpNameSync({
    dir: cacheDirectory
  });
  tmp.setGracefulCleanup();

  function onError(error) {
    self.cacheLogError('error tar-ing ' + installedDirectory + ' :' + error);
    onFinally();
    callback(error);
  }

  function onEnd() {
    fs.renameSync(tmpName, cachePath);
    self.cacheLogInfo('installed and archived dependencies');
    onFinally();
    callback();
  }

  function onFinally() {
    if (fs.existsSync(fileBackupDirectory)) {
      fs.removeSync(fileBackupDirectory);
    }

    if (fs.existsSync(tmpName)) {
      fs.removeSync(tmpName);
    }
  }

  var installedDirectoryStream = fstream.Reader({path: installedDirectory}).on('error', onError);

  if (this.config.noArchive) {
    installedDirectoryStream.on('end', onEnd)
                            .pipe(fstream.Writer({path: tmpName, type: 'Directory'}));
  } else {
    var packer = tar.Pack({ noProprietary: true })
                    .on('error', onError)
                    .on('end', onEnd);
    installedDirectoryStream.pipe(packer)
                            .pipe(fs.createWriteStream(tmpName));
  }
};

CacheDependencyManager.prototype.installCachedDependencies = function (cachePath, compressedCacheExists, callback) {
  var self = this;
  var installDirectory = getAbsolutePath(this.config.installDirectory);
  var fileBackupDirectory = getFileBackupPath(installDirectory);
  var targetPath = path.dirname(installDirectory);
  this.cacheLogInfo('clearing installed dependencies at ' + installDirectory);
  fs.removeSync(installDirectory);
  this.cacheLogInfo('...cleared');
  this.cacheLogInfo('retrieving dependencies from ' + cachePath);

  function onError(error) {
    self.cacheLogError('Error retrieving ' + cachePath + ': ' + error);
    callback(error);
  }
  function onEnd() {
    if (self.config.addToArchiveAndRestore) {
      self.restoreFile(fileBackupDirectory, self.config.addToArchiveAndRestore);
      fs.removeSync(fileBackupDirectory);
    }
    self.cacheLogInfo('done extracting');
    callback();
  }

  if (compressedCacheExists) {
    var extractor = tar.Extract({path: targetPath})
        .on('error', onError)
        .on('end', onEnd);

    fs.createReadStream(cachePath)
        .on('error', onError)
        .pipe(extractor);
  } else {
    fstream.Reader(cachePath)
        .on('error', onError)
        .on('end', onEnd)
        .pipe(fstream.Writer(targetPath));
  }
};

CacheDependencyManager.prototype.loadDependencies = function (callback) {
  var self = this;
  var error = null;

  // Check if config file for dependency manager exists
  if (! fs.existsSync(this.config.configPath)) {
    this.cacheLogInfo('Dependency config file ' + this.config.configPath + ' does not exist. Skipping install');
    callback(null);
    return;
  }
  this.cacheLogInfo('config file exists');

  // Check if package manger CLI is installed
  try {
    which.sync(this.config.cliName);
    this.cacheLogInfo('cli exists');
  }
  catch (e) {
    error = 'Command line tool ' + this.config.cliName + ' not installed';
    this.cacheLogError(error);
    callback(error);
    return;
  }

  // Get hash of dependency config file
  var hash = this.config.getFileHash(this.config.configPath);
  hash = md5(cacheVersion + hash);
  this.cacheLogInfo('hash of ' + this.config.configPath + ': ' + hash);
  // cachePath is absolute path to where local cache of dependencies is located
  var cacheDirectory = path.resolve(this.config.cacheDirectory, this.config.cliName, this.config.getCliVersion());
  var cachePathArchive = path.resolve(cacheDirectory, hash + '.tar.gz');
  var cachePathNotArchived = path.resolve(cacheDirectory, hash);

  // Check if local cache of dependencies exists
  var cacheArchiveExists = fs.existsSync(cachePathArchive);
  var cacheNotArchivedExists = fs.existsSync(cachePathNotArchived);
  if (!this.config.forceRefresh && (cacheArchiveExists || cacheNotArchivedExists)) {
    this.cacheLogInfo('cache exists');

    // Try to retrieve cached dependencies
    this.installCachedDependencies(
      cacheArchiveExists ? cachePathArchive : cachePathNotArchived,
      cacheArchiveExists,
      callback
    );

  } else { // install dependencies with CLI tool and cache
    // Try to install dependencies using package manager
    error = this.installDependencies();
    if (error !== null) {
      callback(error);
      return;
    }

    // Try to archive newly installed dependencies
    var cachePathWithInstalledDirectory = path.resolve(cachePathNotArchived, this.config.installDirectory);
      this.archiveDependencies(
      this.config.noArchive ? cachePathNotArchived : cacheDirectory,
      this.config.noArchive ? cachePathWithInstalledDirectory : cachePathArchive,
      callback
    );
  }
};

/**
 * only return 'composer', 'npm' and 'bower' thereby `npm-cache install` doesn't change behavior if managers are added
 *
 * @returns {Object} availableDefaultManagers
 */
CacheDependencyManager.getAvailableDefaultManagers = function() {
  return _.pick(CacheDependencyManager.getAvailableManagers(), ['composer', 'npm', 'bower']);
};

/**
 * Looks for available package manager configs in cacheDependencyManagers
 * directory. Returns an object with package manager names as keys
 * and absolute paths to configs as values
 *
 * Ex: {
 *  npm: /usr/local/lib/node_modules/npm-cache/cacheDependencyMangers/npmConfig.js,
 *  bower: /usr/local/lib/node_modules/npm-cache/cacheDependencyMangers/bowerConfig.js
 * }
 *
 * @return {Object} availableManagers
 */
CacheDependencyManager.getAvailableManagers = function () {
  if (CacheDependencyManager.managers === undefined) {
    CacheDependencyManager.managers = {};
    var files = fs.readdirSync(__dirname);
    var managerRegex = /(\S+)Config\.js/;
    files.forEach(
      function addAvailableManager (file) {
        var result = managerRegex.exec(file);
        if (result !== null) {
          var managerName = result[1];
          CacheDependencyManager.managers[managerName] = path.join(__dirname, file);
        }
      }
    );
  }
  return CacheDependencyManager.managers;
};

module.exports = CacheDependencyManager;
<commit_msg>Fix --forceRefresh with the —noArchive option<commit_after>'use strict';

var fs = require('fs-extra');
var path = require('path');
var logger = require('../util/logger');
var shell = require('shelljs');
var which = require('which');
var tar = require('tar');
var fstream = require('fstream');
var md5 = require('md5');
var tmp = require('tmp');
var _ = require('lodash');

var cacheVersion = '1';

function CacheDependencyManager (config) {
  this.config = config;
}

// Given a path relative to process' current working directory,
// returns a normalized absolute path
var getAbsolutePath = function (relativePath) {
  return path.resolve(process.cwd(), relativePath);
};

var getFileBackupPath = function (installedDirectory) {
  return path.join(installedDirectory, '.npm-cache');
};

var getFileBackupFilename = function (file) {
  return path.basename(file) + '_' + md5(file);
};

CacheDependencyManager.prototype.cacheLogInfo = function (message) {
  logger.logInfo('[' + this.config.cliName + '] ' + message);
};

CacheDependencyManager.prototype.cacheLogError = function (error) {
  logger.logError('[' + this.config.cliName + '] ' + error);
};

CacheDependencyManager.prototype.installDependencies = function () {
  var error = null;
  var installCommand = this.config.installCommand + ' ' + this.config.installOptions;
  installCommand = installCommand.trim();
  this.cacheLogInfo('running [' + installCommand + ']...');
  if (shell.exec(installCommand).code !== 0) {
    error = 'error running ' + this.config.installCommand;
    this.cacheLogError(error);
  } else {
    this.cacheLogInfo('installed ' + this.config.cliName + ' dependencies, now archiving');
  }
  return error;
};

CacheDependencyManager.prototype.backupFile = function (backupPath, file) {
  var sourceFile = getAbsolutePath(file);
  var backupFilename = getFileBackupFilename(file);
  var backupFile = path.join(backupPath, backupFilename);
  if (!fs.existsSync(sourceFile)) {
    this.cacheLogError('backup file [file not found]:' + file);
    return;
  }

  fs.mkdirsSync(backupPath);
  fs.copySync(sourceFile, backupFile);
  this.cacheLogInfo('backup file: ' + file);
};

CacheDependencyManager.prototype.restoreFile = function (backupPath, file) {
  var sourceFile = getAbsolutePath(file);
  var backupFilename = getFileBackupFilename(file);
  var backupFile = path.join(backupPath, backupFilename);
  if (!fs.existsSync(backupFile)) {
    this.cacheLogError('restore file [file not found]:' + file);
    return;
  }

  fs.copySync(backupFile, sourceFile);
  this.cacheLogInfo('restore file: ' + file);
};

CacheDependencyManager.prototype.archiveDependencies = function (cacheDirectory, cachePath, callback) {
  var self = this;
  var error = null;
  var installedDirectory = getAbsolutePath(this.config.installDirectory);
  var fileBackupDirectory = getFileBackupPath(installedDirectory);
  this.cacheLogInfo('archiving dependencies from ' + installedDirectory);

  if (!fs.existsSync(installedDirectory)) {
    this.cacheLogInfo('skipping archive. Install directory does not exist.');
    return error;
  }

  if (this.config.addToArchiveAndRestore) {
    this.backupFile(fileBackupDirectory, this.config.addToArchiveAndRestore);
  }

  // Make sure cache directory is created
  fs.mkdirsSync(cacheDirectory);

  var tmpName = tmp.tmpNameSync({
    dir: cacheDirectory
  });
  tmp.setGracefulCleanup();

  function onError(error) {
    self.cacheLogError('error tar-ing ' + installedDirectory + ' :' + error);
    onFinally();
    callback(error);
  }

  function onEnd() {
    if (fs.existsSync(cachePath)) {
      fs.removeSync(cachePath);
    }
    fs.renameSync(tmpName, cachePath);
    self.cacheLogInfo('installed and archived dependencies');
    onFinally();
    callback();
  }

  function onFinally() {
    if (fs.existsSync(fileBackupDirectory)) {
      fs.removeSync(fileBackupDirectory);
    }

    if (fs.existsSync(tmpName)) {
      fs.removeSync(tmpName);
    }
  }

  var installedDirectoryStream = fstream.Reader({path: installedDirectory}).on('error', onError);

  if (this.config.noArchive) {
    installedDirectoryStream.on('end', onEnd)
                            .pipe(fstream.Writer({path: tmpName, type: 'Directory'}));
  } else {
    var packer = tar.Pack({ noProprietary: true })
                    .on('error', onError)
                    .on('end', onEnd);
    installedDirectoryStream.pipe(packer)
                            .pipe(fs.createWriteStream(tmpName));
  }
};

CacheDependencyManager.prototype.installCachedDependencies = function (cachePath, compressedCacheExists, callback) {
  var self = this;
  var installDirectory = getAbsolutePath(this.config.installDirectory);
  var fileBackupDirectory = getFileBackupPath(installDirectory);
  var targetPath = path.dirname(installDirectory);
  this.cacheLogInfo('clearing installed dependencies at ' + installDirectory);
  fs.removeSync(installDirectory);
  this.cacheLogInfo('...cleared');
  this.cacheLogInfo('retrieving dependencies from ' + cachePath);

  function onError(error) {
    self.cacheLogError('Error retrieving ' + cachePath + ': ' + error);
    callback(error);
  }
  function onEnd() {
    if (self.config.addToArchiveAndRestore) {
      self.restoreFile(fileBackupDirectory, self.config.addToArchiveAndRestore);
      fs.removeSync(fileBackupDirectory);
    }
    self.cacheLogInfo('done extracting');
    callback();
  }

  if (compressedCacheExists) {
    var extractor = tar.Extract({path: targetPath})
        .on('error', onError)
        .on('end', onEnd);

    fs.createReadStream(cachePath)
        .on('error', onError)
        .pipe(extractor);
  } else {
    fstream.Reader(cachePath)
        .on('error', onError)
        .on('end', onEnd)
        .pipe(fstream.Writer(targetPath));
  }
};

CacheDependencyManager.prototype.loadDependencies = function (callback) {
  var self = this;
  var error = null;

  // Check if config file for dependency manager exists
  if (! fs.existsSync(this.config.configPath)) {
    this.cacheLogInfo('Dependency config file ' + this.config.configPath + ' does not exist. Skipping install');
    callback(null);
    return;
  }
  this.cacheLogInfo('config file exists');

  // Check if package manger CLI is installed
  try {
    which.sync(this.config.cliName);
    this.cacheLogInfo('cli exists');
  }
  catch (e) {
    error = 'Command line tool ' + this.config.cliName + ' not installed';
    this.cacheLogError(error);
    callback(error);
    return;
  }

  // Get hash of dependency config file
  var hash = this.config.getFileHash(this.config.configPath);
  hash = md5(cacheVersion + hash);
  this.cacheLogInfo('hash of ' + this.config.configPath + ': ' + hash);
  // cachePath is absolute path to where local cache of dependencies is located
  var cacheDirectory = path.resolve(this.config.cacheDirectory, this.config.cliName, this.config.getCliVersion());
  var cachePathArchive = path.resolve(cacheDirectory, hash + '.tar.gz');
  var cachePathNotArchived = path.resolve(cacheDirectory, hash);

  // Check if local cache of dependencies exists
  var cacheArchiveExists = fs.existsSync(cachePathArchive);
  var cacheNotArchivedExists = fs.existsSync(cachePathNotArchived);
  if (!this.config.forceRefresh && (cacheArchiveExists || cacheNotArchivedExists)) {
    this.cacheLogInfo('cache exists');

    // Try to retrieve cached dependencies
    this.installCachedDependencies(
      cacheArchiveExists ? cachePathArchive : cachePathNotArchived,
      cacheArchiveExists,
      callback
    );

  } else { // install dependencies with CLI tool and cache
    // Try to install dependencies using package manager
    error = this.installDependencies();
    if (error !== null) {
      callback(error);
      return;
    }

    // Try to archive newly installed dependencies
    var cachePathWithInstalledDirectory = path.resolve(cachePathNotArchived, this.config.installDirectory);
      this.archiveDependencies(
      this.config.noArchive ? cachePathNotArchived : cacheDirectory,
      this.config.noArchive ? cachePathWithInstalledDirectory : cachePathArchive,
      callback
    );
  }
};

/**
 * only return 'composer', 'npm' and 'bower' thereby `npm-cache install` doesn't change behavior if managers are added
 *
 * @returns {Object} availableDefaultManagers
 */
CacheDependencyManager.getAvailableDefaultManagers = function() {
  return _.pick(CacheDependencyManager.getAvailableManagers(), ['composer', 'npm', 'bower']);
};

/**
 * Looks for available package manager configs in cacheDependencyManagers
 * directory. Returns an object with package manager names as keys
 * and absolute paths to configs as values
 *
 * Ex: {
 *  npm: /usr/local/lib/node_modules/npm-cache/cacheDependencyMangers/npmConfig.js,
 *  bower: /usr/local/lib/node_modules/npm-cache/cacheDependencyMangers/bowerConfig.js
 * }
 *
 * @return {Object} availableManagers
 */
CacheDependencyManager.getAvailableManagers = function () {
  if (CacheDependencyManager.managers === undefined) {
    CacheDependencyManager.managers = {};
    var files = fs.readdirSync(__dirname);
    var managerRegex = /(\S+)Config\.js/;
    files.forEach(
      function addAvailableManager (file) {
        var result = managerRegex.exec(file);
        if (result !== null) {
          var managerName = result[1];
          CacheDependencyManager.managers[managerName] = path.join(__dirname, file);
        }
      }
    );
  }
  return CacheDependencyManager.managers;
};

module.exports = CacheDependencyManager;
<|endoftext|>


<commit_before>const express = require('express');
const SimpleMarkdown = require('./simple-markdown');

const app = express();
const packagejson = require('./package.json');

app.get('/api/babelmark', (req, res) => {
  const source = req.query.text || "please provide a \\?text= param";
  const result = SimpleMarkdown.markdownToHtml(source);
  res.json({
    name: 'simple-markdown.js',
    version: packagejson.version,
    html: result
  });
});

app.listen(process.env.PORT || 3000);
<commit_msg>Change babelmark to use <p> tags instead of <div> tags<commit_after>const express = require('express');
const SimpleMarkdown = require('./simple-markdown');

const app = express();
const packagejson = require('./package.json');

// Use <p> tags instead of <div class="paragraph"> for compatibility
const rules = Object.assign({}, SimpleMarkdown.defaultRules, {
  paragraph: Object.assign({}, SimpleMarkdown.defaultRules.paragraph, {
    html: (node, output, state) => {
      return SimpleMarkdown.htmlTag('p', output(node.content, state));
    },
  }),
});

const parse = SimpleMarkdown.parserFor(rules);
const output = SimpleMarkdown.outputFor(rules, 'html');

app.get('/api/babelmark', (req, res) => {
  const source = req.query.text || "please provide a \\?text= param";
  const result = output(parse(source));
  res.json({
    name: 'simple-markdown.js',
    version: packagejson.version,
    html: result
  });
});

app.listen(process.env.PORT || 3000);
<|endoftext|>


<commit_before>const {
  setupComponent,
  checkWrap,
  checkWrapActions,
  initialState,
  defaultLang,
  languages,
  _appPath
} = require('../../_shared.js');

const EditControls = require(_appPath + 'components/edit/EditControls').default;

describe('Testing EditControls Component.', () => {

  beforeEach(() => console.log = jest.fn());

  const checkShowEditControls = (pending, lang) => {
    const _initialState = { ...initialState,
      common: { ...initialState.common,
        userLanguage: lang,
      },
      edit: { ...initialState.edit,
        update: { ...initialState.edit.update,
          pending: pending
        }
      }
    };
    const {wrapper} = setupComponent(EditControls, _initialState);
    const i18n = require(_appPath + 'i18n/' + lang);

    checkWrap(wrapper.find('[data-test-id="EditControls"]'), {
      className: 'form-group form-inline'
    });

    checkWrap(wrapper.find('[data-test-id="button-save-and-close"]').first(), {
      text: i18n['EditControls.button_save_and_close'],
      className: pending ? 'loader' : '',
      disabled: pending,
      type: 'button'
    });

    checkWrap(wrapper.find('[data-test-id="button-save"]').first(), {
      text: i18n['EditControls.button_save'],
      className: pending ? 'loader' : '',
      disabled: pending,
      type: 'button'
    });

    checkWrap(wrapper.find('[data-test-id="cancel-link"]').first(), {
      text: i18n['EditControls.button_reset'],
      className: 'cancel-link'
    });

    wrapper.unmount();
  };

  languages.forEach(lang => {

    it('should show component, that is sending the request',
      () => checkShowEditControls(true, lang.id)
    );

    it('should show component, that is not sending the request',
      () => checkShowEditControls(false, lang.id)
    );
  });

  it('should correctly handle actions on component', () => {
    const _initialState = { ...initialState,
      common: { ...initialState.common,
        userLanguage: defaultLang
      },
      edit: { ...initialState.edit,
        termName: 'termName',
        change: { meanings: [] }
      }
    };
    const _props = {
      dispatch: jest.fn()
    };
    const {wrapper, store} = setupComponent(EditControls, _initialState, _props);

    let actionsCount = 0;
    checkWrapActions(store, actionsCount);

    wrapper.find('[data-test-id="button-save-and-close"]').first().props().onClick({});
    checkWrapActions(store, ++actionsCount);

    wrapper.find('[data-test-id="button-save"]').first().props().onClick({});
    checkWrapActions(store, ++actionsCount);

    wrapper.find('[data-test-id="cancel-link"]').props().onClick({preventDefault: () => {}});
    checkWrapActions(store, ++actionsCount);
  });
});
<commit_msg>Delete old EditControls.spec.js...<commit_after><|endoftext|>


<commit_before>$p.openOutgoingMailDialog = function ($control) {
    var error = 0;
    if ($('#OutgoingMails_Title').length === 0) {
        error = $p.syncSend($control, 'OutgoingMailsForm');
    }
    if (error === 0) {
        $('#OutgoingMailDialog').dialog({
            modal: true,
            width: '90%',
            height: 'auto',
            dialogClass: 'outgoing-mail'
        });
    }
}

$p.openOutgoingMailReplyDialog = function ($control) {
    $p.getData($('#OutgoingMailsForm')).OutgoingMails_OutgoingMailId = $control.attr('data-id');
    $p.syncSend($control, 'OutgoingMailsForm');
    $('#OutgoingMailDialog').dialog({
        modal: true,
        width: '90%',
        height: 'auto',
        dialogClass: 'outgoing-mail'
    });
}

$p.sendMail = function ($control) {
    $p.getData($('#OutgoingMailForm')).Ver = $('._Ver')[0].innerHTML;
    $p.send($control);
}

$p.initOutgoingMailDialog = function () {
    if ($('#OutgoingMails_Reply').val() !== '1') {
        $('#OutgoingMails_Title').val($('#HeaderTitle').text());
        $('#OutgoingMails_Body').val($('#' + $p.tableName() + '_Body').val() +
            '\n\n' + $('#OutgoingMails_Location').val());
    }
    $p.addMailAddress($('#OutgoingMails_To'), $('#To').val());
    $p.addMailAddress($('#OutgoingMails_Cc'), $('#Cc').val());
    $p.addMailAddress($('#OutgoingMails_Bcc'), $('#Bcc').val());
}

$p.addMailAddress = function ($control, defaultMailAddresses) {
    var mailAddresses = defaultMailAddresses !== undefined
        ? defaultMailAddresses
        : $('#OutgoingMails_MailAddresses').find('.ui-selected').map(function () {
            return unescape($(this).text());
        }).get().join(';');
    if (mailAddresses) {
        mailAddresses.split(';').forEach(function (mailAddress) {
            if (mailAddress) {
                $p.addBasket($control, mailAddress);
            }
        });
    }
    $p.setData($control);
}<commit_msg>Bug fixed: 内容項目がフォームに存在しない場合にメール本文にundefinedと入力される問題を解消。<commit_after>$p.openOutgoingMailDialog = function ($control) {
    var error = 0;
    if ($('#OutgoingMails_Title').length === 0) {
        error = $p.syncSend($control, 'OutgoingMailsForm');
    }
    if (error === 0) {
        $('#OutgoingMailDialog').dialog({
            modal: true,
            width: '90%',
            height: 'auto',
            dialogClass: 'outgoing-mail'
        });
    }
}

$p.openOutgoingMailReplyDialog = function ($control) {
    $p.getData($('#OutgoingMailsForm')).OutgoingMails_OutgoingMailId = $control.attr('data-id');
    $p.syncSend($control, 'OutgoingMailsForm');
    $('#OutgoingMailDialog').dialog({
        modal: true,
        width: '90%',
        height: 'auto',
        dialogClass: 'outgoing-mail'
    });
}

$p.sendMail = function ($control) {
    $p.getData($('#OutgoingMailForm')).Ver = $('._Ver')[0].innerHTML;
    $p.send($control);
}

$p.initOutgoingMailDialog = function () {
    var body = $('#' + $p.tableName() + '_Body').val();
    body = body !== undefined ? body + '\n\n' : '';
    if ($('#OutgoingMails_Reply').val() !== '1') {
        $('#OutgoingMails_Title').val($('#HeaderTitle').text());
        $('#OutgoingMails_Body').val(body + $('#OutgoingMails_Location').val());
    }
    $p.addMailAddress($('#OutgoingMails_To'), $('#To').val());
    $p.addMailAddress($('#OutgoingMails_Cc'), $('#Cc').val());
    $p.addMailAddress($('#OutgoingMails_Bcc'), $('#Bcc').val());
}

$p.addMailAddress = function ($control, defaultMailAddresses) {
    var mailAddresses = defaultMailAddresses !== undefined
        ? defaultMailAddresses
        : $('#OutgoingMails_MailAddresses').find('.ui-selected').map(function () {
            return unescape($(this).text());
        }).get().join(';');
    if (mailAddresses) {
        mailAddresses.split(';').forEach(function (mailAddress) {
            if (mailAddress) {
                $p.addBasket($control, mailAddress);
            }
        });
    }
    $p.setData($control);
}<|endoftext|>