<commit_before>/**
 * WebHemi Components: Form
 *
 * @copyright 2012 - 2018 Gixx-web (http://www.gixx-web.com)
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
 * @link      http://www.gixx-web.com
 */

if (typeof formOptions === 'undefined') {
    let formOptions = {
        verbose: WebHemiOptions.verbose
    };
}

/**
 * Form Component.
 *
 * @type {{init}}
 */
WebHemi.components.Form = function ()
{
    "use strict";

    /** @type {boolean} */
    let initialized = false;
    /** @type {NodeList} */
    let formElements = [];
    /** @type {number} */
    let idCounter = 1;
    /** @type {string} */
    let formIdPrefix = 'webhemi-form-';
    /** @type {Object} */
    let options = WebHemi.getOptions();
    /** @type {Object} */
    let formDefaultOptions = {
        ajaxFlagAttribute: 'data-isAjax'
    };

    if (typeof WebHemi.components.Util === 'undefined') {
        throw new ReferenceError('The Util component is required to use this component.');
    }

    /** @type Util */
    let Util = WebHemi.components.Util;

    // Complete the missing option elements.
    for (let i in formDefaultOptions) {
        if (formDefaultOptions.hasOwnProperty(i) && typeof options.availableComponents.Form[i] === 'undefined') {
            options.availableComponents.Form[i] = formDefaultOptions[i];
        }
    }

    let formOptions = options.availableComponents.Form;

    /**
     * Adds special functionality to
     * @param HTMLElement
     * @return {{constructor: FormElement, onBeforeSubmit: onBeforeSubmit, onSuccess: onSuccess, onFailure: onFailure}}
     * @constructor
     */
    let FormElement = function(HTMLElement)
    {
        let isAjax = typeof HTMLElement.dataset.ajax !== 'undefined' ? HTMLElement.dataset.asynch : false;
        let isAsynch = typeof HTMLElement.dataset.asynch !== 'undefined' ? HTMLElement.dataset.asynch : true;
        let targetUrl = HTMLElement.getAttribute('action');
        let method = HTMLElement.hasAttribute('action') ? HTMLElement.getAttribute('method') : 'POST';
        let enctype = HTMLElement.hasAttribute('enctype') ? HTMLElement.getAttribute('enctype') : 'application/json';

        if (enctype === 'text/plain') {
            enctype = 'application/json';
        }

        let onBeforeSubmitCallback;
        let onSuccessCallback;
        let onFailureCallback;

        /**
         * Handles the form submit event.
         *
         * @param {Event} event
         * @return {boolean}
         */
        let submitForm = function(event)
        {
            if (typeof onBeforeSubmitCallback !== 'undefined') {
                let returnValue = onBeforeSubmitCallback(event);

                if (returnValue === false) {
                    return false;
                }
            }

            if (isAjax) {
                event.preventDefault();

                let formData = new FormData(HTMLElement);

                Util.ajax({
                    url: targetUrl,
                    data: formData,
                    enctype: enctype,
                    method: method,
                    async: isAsynch,
                    success: onSuccessCallback,
                    failure: onFailureCallback
                });
            }

            options.verbose && console.info(
                '%c⚡%c an Form element was submitted. %o',
                'color:orange;font-weight:bold',
                'color:#599bd6',
                '#'+HTMLElement.getAttribute('id')
            );
        };

        // Fix
        if (targetUrl === '') {
            targetUrl = location.href;
        }

        if (targetUrl.slice(-1) !== '/') {
            targetUrl = targetUrl + '/';
        }

        HTMLElement.setAttribute('action', targetUrl);

        Util.addEventListeners([HTMLElement], 'submit', submitForm, this);

        options.verbose && console.info(
            '%c✚%c a'+(isAjax ? 'n Ajax' : '')+' Form element is initialized %o',
            'color:green; font-weight:bold;',
            'color:black;',
            '#'+HTMLElement.getAttribute('id')
        );

        return {
            constructor : FormElement,

            /**
             * Waiting for a callback function. Fires right before the submit.
             *
             * @param {function} callback
             */
            onBeforeSubmit : function(callback)
            {
                if (typeof callback === 'function') {
                    onBeforeSubmitCallback = callback;
                }
            },

            /**
             * Waiting for a callback function. Fires only for AjaxForms when the reponse is a success.
             *
             * @param {function} callback
             */
            onSuccess: function(callback)
            {
                if (typeof callback === 'function') {
                    onSuccessCallback = callback;
                }
            },

            /**
             * Waiting for a callback function. Fires only for AjaxForms when the reponse is a failure.
             *
             * @param {function} callback
             */
            onFailure: function(callback)
            {
                if (typeof callback === 'function') {
                    onFailureCallback = callback;
                }
            }
        }
    };

    if (typeof Util === 'undefined') {
        throw new ReferenceError('The Util component is required to use this component.');
    }

    options.verbose && console.info(
        '%c✔%c the Form component is loaded.',
        'color:green; font-weight:bold;',
        'color:black; font-weight:bold;'
    );

    return {
        /**
         * Initializes the loader and collects the elements.
         */
        init : function()
        {
            if (initialized) {
                return;
            }

            options.verbose && console.group(
                '%c  Looking for Form Elements...',
                'color:#cecece'
            );

            formElements = document.querySelectorAll('form');

            if (formElements.length > 0) {
                for (let i = 0, len = formElements.length; i < len; i++) {
                    if (!formElements[i].hasAttribute('id')) {
                        formElements[i].setAttribute('id', formIdPrefix + (idCounter++));
                    }

                    formElements[i].component = new FormElement(formElements[i]);
                }
            } else {
                options.verbose && console.info(
                    '%c  No Form Elements found.',
                    'color:#cecece; font-weight:bold;'
                );
            }

            options.verbose && console.groupEnd();

            Util.triggerEvent(document, 'WebHemi.Component.Form.Ready');
            initialized = true;
        }
    };
}();
<commit_msg>Fix weird naming<commit_after>/**
 * WebHemi Components: Form
 *
 * @copyright 2012 - 2018 Gixx-web (http://www.gixx-web.com)
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
 * @link      http://www.gixx-web.com
 */

if (typeof formOptions === 'undefined') {
    let formOptions = {
        verbose: WebHemiOptions.verbose
    };
}

/**
 * Form Component.
 *
 * @type {{init}}
 */
WebHemi.components.Form = function ()
{
    "use strict";

    /** @type {boolean} */
    let initialized = false;
    /** @type {NodeList} */
    let formElements = [];
    /** @type {number} */
    let idCounter = 1;
    /** @type {string} */
    let formIdPrefix = 'webhemi-form-';
    /** @type {Object} */
    let options = WebHemi.getOptions();
    /** @type {Object} */
    let formDefaultOptions = {
        ajaxFlagAttribute: 'data-isAjax'
    };

    if (typeof WebHemi.components.Util === 'undefined') {
        throw new ReferenceError('The Util component is required to use this component.');
    }

    /** @type Util */
    let Util = WebHemi.components.Util;

    // Complete the missing option elements.
    for (let i in formDefaultOptions) {
        if (formDefaultOptions.hasOwnProperty(i) && typeof options.availableComponents.Form[i] === 'undefined') {
            options.availableComponents.Form[i] = formDefaultOptions[i];
        }
    }

    let formOptions = options.availableComponents.Form;

    /**
     * Adds special functionality to
     * @param HTMLElement
     * @return {{constructor: FormElement, onBeforeSubmit: onBeforeSubmit, onSuccess: onSuccess, onFailure: onFailure}}
     * @constructor
     */
    let FormElement = function(HTMLElement)
    {
        let isAjax = typeof HTMLElement.dataset.ajax !== 'undefined' ? Util.inArray(HTMLElement.dataset.ajax, [1, true, '1', 'true'])  : false;
        let isAsync = typeof HTMLElement.dataset.asynch !== 'undefined' ? Util.inArray(HTMLElement.dataset.async, [1, true, '1', 'true']) : true;
        let targetUrl = HTMLElement.getAttribute('action');
        let method = HTMLElement.hasAttribute('action') ? HTMLElement.getAttribute('method') : 'POST';
        let enctype = HTMLElement.hasAttribute('enctype') ? HTMLElement.getAttribute('enctype') : 'application/json';

        if (enctype === 'text/plain') {
            enctype = 'application/json';
        }

        let onBeforeSubmitCallback;
        let onSuccessCallback;
        let onFailureCallback;

        /**
         * Handles the form submit event.
         *
         * @param {Event} event
         * @return {boolean}
         */
        let submitForm = function(event)
        {
            if (typeof onBeforeSubmitCallback !== 'undefined') {
                let returnValue = onBeforeSubmitCallback(event);

                if (returnValue === false) {
                    return false;
                }
            }

            if (isAjax) {
                event.preventDefault();

                let formData = new FormData(HTMLElement);

                Util.ajax({
                    url: targetUrl,
                    data: formData,
                    enctype: enctype,
                    method: method,
                    async: isAsync,
                    success: onSuccessCallback,
                    failure: onFailureCallback
                });
            }

            options.verbose && console.info(
                '%c⚡%c an Form element was submitted. %o',
                'color:orange;font-weight:bold',
                'color:#599bd6',
                '#'+HTMLElement.getAttribute('id')
            );
        };

        // Fix
        if (targetUrl === '') {
            targetUrl = location.href;
        }

        if (targetUrl.slice(-1) !== '/') {
            targetUrl = targetUrl + '/';
        }

        HTMLElement.setAttribute('action', targetUrl);

        Util.addEventListeners([HTMLElement], 'submit', submitForm, this);

        options.verbose && console.info(
            '%c✚%c a'+(isAjax ? 'n Ajax' : '')+' Form element is initialized %o',
            'color:green; font-weight:bold;',
            'color:black;',
            '#'+HTMLElement.getAttribute('id')
        );

        return {
            constructor : FormElement,

            /**
             * Waiting for a callback function. Fires right before the submit.
             *
             * @param {function} callback
             */
            onBeforeSubmit : function(callback)
            {
                if (typeof callback === 'function') {
                    onBeforeSubmitCallback = callback;
                }
            },

            /**
             * Waiting for a callback function. Fires only for AjaxForms when the reponse is a success.
             *
             * @param {function} callback
             */
            onSuccess: function(callback)
            {
                if (typeof callback === 'function') {
                    onSuccessCallback = callback;
                }
            },

            /**
             * Waiting for a callback function. Fires only for AjaxForms when the reponse is a failure.
             *
             * @param {function} callback
             */
            onFailure: function(callback)
            {
                if (typeof callback === 'function') {
                    onFailureCallback = callback;
                }
            }
        }
    };

    if (typeof Util === 'undefined') {
        throw new ReferenceError('The Util component is required to use this component.');
    }

    options.verbose && console.info(
        '%c✔%c the Form component is loaded.',
        'color:green; font-weight:bold;',
        'color:black; font-weight:bold;'
    );

    return {
        /**
         * Initializes the loader and collects the elements.
         */
        init : function()
        {
            if (initialized) {
                return;
            }

            options.verbose && console.group(
                '%c  Looking for Form Elements...',
                'color:#cecece'
            );

            formElements = document.querySelectorAll('form');

            if (formElements.length > 0) {
                for (let i = 0, len = formElements.length; i < len; i++) {
                    if (!formElements[i].hasAttribute('id')) {
                        formElements[i].setAttribute('id', formIdPrefix + (idCounter++));
                    }

                    formElements[i].component = new FormElement(formElements[i]);
                }
            } else {
                options.verbose && console.info(
                    '%c  No Form Elements found.',
                    'color:#cecece; font-weight:bold;'
                );
            }

            options.verbose && console.groupEnd();

            Util.triggerEvent(document, 'WebHemi.Component.Form.Ready');
            initialized = true;
        }
    };
}();
<|endoftext|>


<commit_before>/* jshint node: true */
/* jshint esnext: true */
'use strict';

const PDFDocument = require('pdfkit');
const qr = require('qr-image');
const _ = require('lodash');
const Q = require('q');
const config = require('config');
const participants = require('../service/participants');
const tshirts = require('../service/tshirts');
const barcode = require("rescode");

let pdfGeneration = {};

const fileName = 'start_numbers.pdf';
const pathToBackgroundImage = '/images/background_light.jpg';
const pathToLogoLeft = '/images/lauf_gegen_rechts_logo.jpg';
const pathToLogoRight = '/images/fc_st_pauli_marathon_logo.png';
const checkmarkSymbolSvg = 'M7.375,25 c0,0,10,11.375,14.125,11.375S44.875,8,44.875,8';

pdfGeneration.addCheckmarkSymbol = (doc) => {
  doc.translate(20, 280)
    .path(checkmarkSymbolSvg)
    .lineWidth(3)
    .stroke();
};

pdfGeneration.createStartNumberPage = (participant, doc) => {
  doc.image(__dirname + pathToBackgroundImage, {fit: [800, 800]});
  doc.image(__dirname + pathToLogoLeft, 20, 20, {fit: [130, 130]});
  doc.image(__dirname + pathToLogoRight, 475, 20, {fit: [100, 100]});

  doc.font('Helvetica-Bold').fontSize(200).fillColor('saddlebrown').text(participant.start_number, 0, 130, {align: 'center'});
  doc.fontSize(40).fillColor('red').text(participant.firstname.substring(0, 17), 0, 300, {align: 'center'});
  doc.fontSize(30).fillColor('red').text(participant.team.substring(0, 25), 0, 350, {align: 'center'});

  barcode.loadModules(["code128"]);
  let barcodeSvg = barcode.create("code128", String(participant.start_number));

  doc.image(barcodeSvg, 260, 20, {fit: [70, 70]});
  doc.image(barcodeSvg, 20, 330, {fit: [70, 70]});
  doc.image(barcodeSvg, 500, 330, {fit: [70, 70]});

  if(participant.tshirt) {
    doc.fontSize(12).fillColor('black').text(participant.tshirt.size + ' ' + participant.tshirt.model, 500, 315);
  }

  if(participant.has_payed) {
    pdfGeneration.addCheckmarkSymbol(doc);
  }

  doc.addPage();
};

pdfGeneration.fillDocument = function(res, doc) {
  const deferred = Q.defer();

  participants.confirmed().then(confirmed =>
    participants.registered().then(unconfirmed => {
      res.writeHead(200, {
        'Content-Type': 'application/pdf',
        'Access-Control-Allow-Origin': '*',
        'Content-Disposition': 'attachment; filename=' + fileName
      });
      doc.pipe(res);

      confirmed.map( (participant) => {
        participant.has_payed = true;
      });

      let allParticipants = confirmed.concat(unconfirmed);
      allParticipants = _.orderBy(allParticipants, ['start_number']);

      Q.all(allParticipants.map(tshirts.findAndAddTo))
        .then(() => {
          _.forEach(allParticipants, participant => {
            pdfGeneration.createStartNumberPage(participant, doc);
          });

          doc.end();
          deferred.resolve(doc);
      });

      return deferred.promise;
    }));
};

pdfGeneration.generate = (res) => {
  let doc = new PDFDocument({size: 'A5', layout: 'landscape', margin: 0});
  return pdfGeneration.fillDocument(res, doc);
};

module.exports = pdfGeneration;
<commit_msg>use start number from the database<commit_after>/* jshint node: true */
/* jshint esnext: true */
'use strict';

const PDFDocument = require('pdfkit');
const qr = require('qr-image');
const _ = require('lodash');
const Q = require('q');
const config = require('config');
const participants = require('../service/participants');
const tshirts = require('../service/tshirts');
const barcode = require("rescode");

let pdfGeneration = {};

const fileName = 'start_numbers.pdf';
const pathToBackgroundImage = '/images/background_light.jpg';
const pathToLogoLeft = '/images/lauf_gegen_rechts_logo.jpg';
const pathToLogoRight = '/images/fc_st_pauli_marathon_logo.png';
const checkmarkSymbolSvg = 'M7.375,25 c0,0,10,11.375,14.125,11.375S44.875,8,44.875,8';

pdfGeneration.addCheckmarkSymbol = (doc) => {
  doc.translate(20, 280)
    .path(checkmarkSymbolSvg)
    .lineWidth(3)
    .stroke();
};

pdfGeneration.createStartNumberPage = (participant, doc) => {
  doc.image(__dirname + pathToBackgroundImage, {fit: [800, 800]});
  doc.image(__dirname + pathToLogoLeft, 20, 20, {fit: [130, 130]});
  doc.image(__dirname + pathToLogoRight, 475, 20, {fit: [100, 100]});

  doc.font('Helvetica-Bold').fontSize(200).fillColor('saddlebrown').text(participant.start_number, 0, 130, {align: 'center'});
  doc.fontSize(40).fillColor('red').text(participant.firstname.substring(0, 17), 0, 300, {align: 'center'});
  doc.fontSize(30).fillColor('red').text(participant.team.substring(0, 25), 0, 350, {align: 'center'});

  barcode.loadModules(["code128"]);
  let barcodeSvg = barcode.create("code128", String(participant.start_number));

  doc.image(barcodeSvg, 260, 20, {fit: [70, 70]});
  doc.image(barcodeSvg, 20, 330, {fit: [70, 70]});
  doc.image(barcodeSvg, 500, 330, {fit: [70, 70]});

  if(participant.tshirt) {
    doc.fontSize(12).fillColor('black').text(participant.tshirt.size + ' ' + participant.tshirt.model, 500, 315);
  }

  if(participant.has_payed) {
    pdfGeneration.addCheckmarkSymbol(doc);
  }

  doc.addPage();
};

pdfGeneration.fillDocument = function(res, doc) {
  const deferred = Q.defer();

  participants.confirmed().then(confirmed =>
    participants.registered().then(unconfirmed => {
      res.writeHead(200, {
        'Content-Type': 'application/pdf',
        'Access-Control-Allow-Origin': '*',
        'Content-Disposition': 'attachment; filename=' + fileName
      });
      doc.pipe(res);

      confirmed.map( (participant) => {
        participant.has_payed = true;
      });

      let allParticipants = confirmed.concat(unconfirmed);
      allParticipants = _.orderBy(allParticipants, ['start_number']);

      Q.all(allParticipants.map(tshirts.findAndAddTo))
        .then(() => {
          _.forEach(allParticipants, participant => {
            pdfGeneration.createStartNumberPage(participant, doc);
          });

          doc.end();
          deferred.resolve(doc);
      });
    }));

  return deferred.promise;
};

pdfGeneration.generate = (res) => {
  let doc = new PDFDocument({size: 'A5', layout: 'landscape', margin: 0});
  return pdfGeneration.fillDocument(res, doc);
};

module.exports = pdfGeneration;
<|endoftext|>


<commit_before>/* function to create popup window */
function popup(mylink){
    if (!window.focus)
        return true;
    var href;
    if (typeof(mylink) == 'string')
       href=mylink;
    else
       href=mylink.href;
    window.open(href, "player", 'width=300,height=100,scrollbars=yes');
    return false;
}

function convertSecondsToDaysHoursMinutesSeconds(seconds){
    if (seconds < 0)
        seconds = 0;

    seconds = parseInt(seconds, 10);

    var days = parseInt(seconds / 86400);
    seconds -= days*86400;

    var hours = parseInt(seconds / 3600);
    seconds -= hours*3600;

    var minutes = parseInt(seconds / 60);
    seconds -= minutes*60;

    return {days:days, hours:hours, minutes:minutes, seconds:seconds};
}

/* Takes an input parameter of milliseconds and converts these into
 * the format HH:MM:SS */
function convertToHHMMSS(timeInMS){
	var time = parseInt(timeInMS);

	var hours = parseInt(time / 3600000);
	time -= 3600000*hours;

	var minutes = parseInt(time / 60000);
	time -= 60000*minutes;

	var seconds = parseInt(time / 1000);

	hours = hours.toString();
	minutes = minutes.toString();
	seconds = seconds.toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;
	if (hours == "00")
		return minutes + ":" + seconds;
	else
		return hours + ":" + minutes + ":" + seconds;
}

function convertToHHMMSSmm(timeInMS){
	var time = parseInt(timeInMS);

	var hours = parseInt(time / 3600000);
	time -= 3600000*hours;

	var minutes = parseInt(time / 60000);
	time -= 60000*minutes;

	var seconds = parseInt(time / 1000);
	time -= 1000*seconds;

	var ms = parseInt(time);

	hours = hours.toString();
	minutes = minutes.toString();
	seconds = seconds.toString();
	ms = ms.toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;

	if (ms.length == 3)
		ms = ms.substring(0, 2);
	else if (ms.length == 2)
		ms = "0" + ms.substring(0,1);
	else if (ms.length == 1)
		ms = "00";

	if (hours == "00")
		return minutes + ":" + seconds + "." + ms;
	else
		return hours + ":" + minutes + ":" + seconds+ "." + ms;
}

function convertDateToHHMM(epochTime){
	var d = new Date(epochTime);

	var hours = d.getUTCHours().toString();
	var minutes = d.getUTCMinutes().toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;

	return hours + ":" + minutes;
}

function convertDateToHHMMSS(epochTime){
	var d = new Date(epochTime);

	var hours = d.getUTCHours().toString();
	var minutes = d.getUTCMinutes().toString();
	var seconds = d.getUTCSeconds().toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;
	return hours + ":" + minutes + ":" + seconds;
}

/* Takes in a string of format similar to 2011-02-07 02:59:57,
 * and converts this to epoch/posix time. */
function convertDateToPosixTime(s){

    var datetime = s.split(" ");

    var date = datetime[0].split("-");
    var time = datetime[1].split(":");

	var year = date[0];
	var month = date[1];
	var day = date[2];
	var hour = time[0];
	var minute = time[1];
    var sec = 0;
    var msec = 0;

    if (time[2].indexOf(".") != -1){
        var temp = time[2].split(".");
        sec = temp[0];
        msec = temp[1];
    } else
        sec = time[2];

	return Date.UTC(year, month-1, day, hour, minute, sec, msec);
}

function getFileExt(filename){
    return filename.split('.').pop();
}

function audioStream(){

    if ($("#jquery_jplayer_1").data("jPlayer") && $("#jquery_jplayer_1").data("jPlayer").status.paused != true){
        $('#jquery_jplayer_1').jPlayer('clearMedia');
        $('#jquery_jplayer_1').jPlayer('destroy');
        return;
    }

    var uri = "http://localhost:8000/airtime_128.ogg";
    var ext = getFileExt(uri);

    var media;
    var supplied;
    if (ext == "ogg"){
        media = {oga:uri};
        supplied = "oga";
    } else {
        media = {mp3:uri};
        supplied = "mp3";
    }

    $("#jquery_jplayer_1").jPlayer({
        ready: function () {
            $(this).jPlayer("setMedia", media).jPlayer("play");
        },
        swfPath: "/js/jplayer",
        supplied: supplied
    });
}

function audioPreview(filename, elemID){

    var elems = $('.ui-icon.ui-icon-pause');
    elems.attr("class", "ui-icon ui-icon-play");

    if ($("#jquery_jplayer_1").data("jPlayer") && $("#jquery_jplayer_1").data("jPlayer").status.paused != true){
         $('#jquery_jplayer_1').jPlayer('stop');
        return;
    }

    var ext = getFileExt(filename);
    var uri = "/api/get-media/file/" + filename;

    var media;
    var supplied;
    if (ext == "ogg"){
        media = {oga:uri};
        supplied = "oga";
    } else {
        media = {mp3:uri};
        supplied = "mp3";
    }

    $("#jquery_jplayer_1").jPlayer("destroy");
    $("#jquery_jplayer_1").jPlayer({
        ready: function () {
            $(this).jPlayer("setMedia", media).jPlayer("play");
        },
        swfPath: "/js/jplayer",
        supplied: supplied,
        wmode:"window"
    });

    $('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause");
}

function resizeImg(ele, targetWidth, targetHeight){
    var img = $(ele);

    var width = ele.width;
    var height = ele.height;

    // resize img proportionaly
    if( width > height && width > targetWidth){
        var ratio = targetWidth/width;
        img.css("width", targetHeight+"px");
        var newHeight = height * ratio;
        img.css("height", newHeight+"px");
    }else if( width < height && height > targetHeight){
        var ratio = targetHeight/height;
        img.css("height", targetHeight+"px");
        var newWidth = width * ratio;
        img.css("width", newWidth+"px");
    }else if( width == height && width > targetWidth){
        img.css("height", targetHeight+"px");
        img.css("width", targetWidth+"px" );
    }
}

function resizeToMaxHeight(ele, targetHeight){
    var img = $(ele);

    var width = ele.width;
    var height = ele.height;

    // resize img proportionaly
    if( height > targetHeight){
        var ratio = targetHeight/height;
        img.css("height", targetHeight+"px");
        var newWidth = width * ratio;
        img.css("width", newWidth+"px");
    }
}
<commit_msg>-remove unused function<commit_after>/* function to create popup window */
function popup(mylink){
    if (!window.focus)
        return true;
    var href;
    if (typeof(mylink) == 'string')
       href=mylink;
    else
       href=mylink.href;
    window.open(href, "player", 'width=300,height=100,scrollbars=yes');
    return false;
}

function convertSecondsToDaysHoursMinutesSeconds(seconds){
    if (seconds < 0)
        seconds = 0;

    seconds = parseInt(seconds, 10);

    var days = parseInt(seconds / 86400);
    seconds -= days*86400;

    var hours = parseInt(seconds / 3600);
    seconds -= hours*3600;

    var minutes = parseInt(seconds / 60);
    seconds -= minutes*60;

    return {days:days, hours:hours, minutes:minutes, seconds:seconds};
}

/* Takes an input parameter of milliseconds and converts these into
 * the format HH:MM:SS */
function convertToHHMMSS(timeInMS){
	var time = parseInt(timeInMS);

	var hours = parseInt(time / 3600000);
	time -= 3600000*hours;

	var minutes = parseInt(time / 60000);
	time -= 60000*minutes;

	var seconds = parseInt(time / 1000);

	hours = hours.toString();
	minutes = minutes.toString();
	seconds = seconds.toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;
	if (hours == "00")
		return minutes + ":" + seconds;
	else
		return hours + ":" + minutes + ":" + seconds;
}

function convertToHHMMSSmm(timeInMS){
	var time = parseInt(timeInMS);

	var hours = parseInt(time / 3600000);
	time -= 3600000*hours;

	var minutes = parseInt(time / 60000);
	time -= 60000*minutes;

	var seconds = parseInt(time / 1000);
	time -= 1000*seconds;

	var ms = parseInt(time);

	hours = hours.toString();
	minutes = minutes.toString();
	seconds = seconds.toString();
	ms = ms.toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;

	if (ms.length == 3)
		ms = ms.substring(0, 2);
	else if (ms.length == 2)
		ms = "0" + ms.substring(0,1);
	else if (ms.length == 1)
		ms = "00";

	if (hours == "00")
		return minutes + ":" + seconds + "." + ms;
	else
		return hours + ":" + minutes + ":" + seconds+ "." + ms;
}

function convertDateToHHMM(epochTime){
	var d = new Date(epochTime);

	var hours = d.getUTCHours().toString();
	var minutes = d.getUTCMinutes().toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;

	return hours + ":" + minutes;
}

function convertDateToHHMMSS(epochTime){
	var d = new Date(epochTime);

	var hours = d.getUTCHours().toString();
	var minutes = d.getUTCMinutes().toString();
	var seconds = d.getUTCSeconds().toString();

	if (hours.length == 1)
		hours = "0" + hours;
	if (minutes.length == 1)
		minutes = "0" + minutes;
	if (seconds.length == 1)
		seconds = "0" + seconds;
	return hours + ":" + minutes + ":" + seconds;
}

/* Takes in a string of format similar to 2011-02-07 02:59:57,
 * and converts this to epoch/posix time. */
function convertDateToPosixTime(s){

    var datetime = s.split(" ");

    var date = datetime[0].split("-");
    var time = datetime[1].split(":");

	var year = date[0];
	var month = date[1];
	var day = date[2];
	var hour = time[0];
	var minute = time[1];
    var sec = 0;
    var msec = 0;

    if (time[2].indexOf(".") != -1){
        var temp = time[2].split(".");
        sec = temp[0];
        msec = temp[1];
    } else
        sec = time[2];

	return Date.UTC(year, month-1, day, hour, minute, sec, msec);
}

function getFileExt(filename){
    return filename.split('.').pop();
}

function audioPreview(filename, elemID){

    var elems = $('.ui-icon.ui-icon-pause');
    elems.attr("class", "ui-icon ui-icon-play");

    if ($("#jquery_jplayer_1").data("jPlayer") && $("#jquery_jplayer_1").data("jPlayer").status.paused != true){
         $('#jquery_jplayer_1').jPlayer('stop');
        return;
    }

    var ext = getFileExt(filename);
    var uri = "/api/get-media/file/" + filename;

    var media;
    var supplied;
    if (ext == "ogg"){
        media = {oga:uri};
        supplied = "oga";
    } else {
        media = {mp3:uri};
        supplied = "mp3";
    }

    $("#jquery_jplayer_1").jPlayer("destroy");
    $("#jquery_jplayer_1").jPlayer({
        ready: function () {
            $(this).jPlayer("setMedia", media).jPlayer("play");
        },
        swfPath: "/js/jplayer",
        supplied: supplied,
        wmode:"window"
    });

    $('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause");
}

function resizeImg(ele, targetWidth, targetHeight){
    var img = $(ele);

    var width = ele.width;
    var height = ele.height;

    // resize img proportionaly
    if( width > height && width > targetWidth){
        var ratio = targetWidth/width;
        img.css("width", targetHeight+"px");
        var newHeight = height * ratio;
        img.css("height", newHeight+"px");
    }else if( width < height && height > targetHeight){
        var ratio = targetHeight/height;
        img.css("height", targetHeight+"px");
        var newWidth = width * ratio;
        img.css("width", newWidth+"px");
    }else if( width == height && width > targetWidth){
        img.css("height", targetHeight+"px");
        img.css("width", targetWidth+"px" );
    }
}

function resizeToMaxHeight(ele, targetHeight){
    var img = $(ele);

    var width = ele.width;
    var height = ele.height;

    // resize img proportionaly
    if( height > targetHeight){
        var ratio = targetHeight/height;
        img.css("height", targetHeight+"px");
        var newWidth = width * ratio;
        img.css("width", newWidth+"px");
    }
}
<|endoftext|>


<commit_before>
/**
 * Pnotifier - Push Notification Services Abstraction
 * 2015 Thomas Bazire <tbazire@evertygo.com>
 * License: MIT
 */

'use strict';

var gcm = require('node-gcm');
var _ = require('lodash');
var sysu = require('util');
var EventEmitter = require('events').EventEmitter;
var utils = require('../lib/utils');

/**
 * Initialize
 * @param {object} params, service parameters
 * @param {object} emitter, EventEmitter (not used yet)
 */
var GcmService = function (params) {
  EventEmitter.call(this);

  this.protocol = 'gcm';
  this.params = params || {};
  this.options = this.params.options || {};
  this.credentials = this.params.credentials || {};
};

sysu.inherits(GcmService, EventEmitter);

/**
 * Create a connexion to the Google Cloud Messaging service.
 * @param {function} next
 */
GcmService.prototype.createConnection = function (next) {

  var required = ['api_key','tokens'];

  try {

    // Check missing parameters
    var missing = utils.missingProperty(required, this.credentials);

    if (!_.isEmpty(missing)) {
      return next(utils.listMissingProperties(missing, 'credentials'));
    }

    this.connection = new gcm.Sender(this.credentials.api_key);
    return next(null);
  } catch (e) {
    next(e);
  }
};

/**
 * Send a notification to the Google Cloud Messaging service.
 * @param {object} data, data to send
 * @param {function} next
 */
GcmService.prototype.send = function (data, next) {

  try {

    var tokens = this.credentials.tokens;
    var message = new gcm.Message(this.options);
    message.addNotification(data);

    this.connection.send(message, { registrationTokens: tokens }, function (err, response) {
      if (err) return next(err);
      next(null, response);
    });

  } catch (e) {
    return next(e);
  }

};

/**
 * Provide protocol (service name)
 */
GcmService.prototype.getProtocol = function () {
  return this.protocol;
}

/**
 * Do nothing except executing the given callback.
 * @param {function} next, callback
 */
GcmService.prototype.close = function (next) {
  if (next) return next();
};

/**
 * Exporting the module
 */
module.exports = GcmService;
<commit_msg>Update gcm.js<commit_after>
/**
 * Pnotifier - Push Notification Services Abstraction
 * 2015 Thomas Bazire <tbazire@evertygo.com>
 * License: MIT
 */

'use strict';

var gcm = require('node-gcm');
var _ = require('lodash');
var sysu = require('util');
var EventEmitter = require('events').EventEmitter;
var utils = require('../lib/utils');

/**
 * Initialize
 * @param {object} params, service parameters
 * @param {object} emitter, EventEmitter (not used yet)
 */
var GcmService = function (params) {
  EventEmitter.call(this);

  this.protocol = 'gcm';
  this.params = params || {};
  this.options = this.params.options || {};
  this.credentials = this.params.credentials || {};
};

sysu.inherits(GcmService, EventEmitter);

/**
 * Create a connexion to the Google Cloud Messaging service.
 * @param {function} next
 */
GcmService.prototype.createConnection = function (next) {

  var required = ['api_key','tokens'];

  try {

    // Check missing parameters
    var missing = utils.missingProperty(required, this.credentials);

    if (!_.isEmpty(missing)) {
      return next(utils.listMissingProperties(missing, 'credentials'));
    }

    this.connection = new gcm.Sender(this.credentials.api_key);
    return next(null);
  } catch (e) {
    next(e);
  }
};

/**
 * Send a notification to the Google Cloud Messaging service.
 * @param {object} data, data to send
 * @param {function} next
 */
GcmService.prototype.send = function (data, next) {

  try {

    var tokens = this.credentials.tokens;
    var message = new gcm.Message(this.options);
//    message.addNotification(data);

    this.connection.send(message, { registrationTokens: tokens }, function (err, response) {
      if (err) return next(err);
      next(null, response);
    });

  } catch (e) {
    return next(e);
  }

};

/**
 * Provide protocol (service name)
 */
GcmService.prototype.getProtocol = function () {
  return this.protocol;
}

/**
 * Do nothing except executing the given callback.
 * @param {function} next, callback
 */
GcmService.prototype.close = function (next) {
  if (next) return next();
};

/**
 * Exporting the module
 */
module.exports = GcmService;
<|endoftext|>


<commit_before>/*global module:false*/

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        meta: {
            css_banner: '/*\n' +
            'Theme Name: Rizikove kaceni teplice based on Sage base wordpress theme' +
            'Author: Jakub Adler\n' +
            '*/\n',
            sass_assets_dir:    'assets/styles',
            js_assets_dir:      'assets/scripts',
            css_dest:           'dist/styles/main.css',
            js_dest:            'dist/scripts/main.js',
            fonts_dest:         'dist/fonts/'
        },
        sass: {
            options:{
              lineNumbers: true
            },
            main: {
                files: {
                   '<%= meta.css_dest %>': '<%= meta.sass_assets_dir %>/main.scss'
                }
            }
        },
        cssmin: {
            main: {
                options: {
                    banner: '<%= meta.css_banner %>'
                },
                files: {
                    '<%= meta.css_dest %>': '<%= meta.css_dest %>'
                }
            }
        },
        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                boss: true,
                eqnull: true,
                browser: true,
                globals: {
                    // jQuery
                    jQuery: true,
                    // extras
                    alert: true,
                    console: true,
                    require: true,
                    $: true,
                    module: true,
                    _ : true,
                    google: true
                }
            },
            all: [
                'Gruntfile.js',
                '<%= meta.js_assets_dir %>/**/*.js'
            ]
        },
        browserify: {
            "app": {
                files: { '<%= meta.js_dest %>': ['<%= meta.js_assets_dir %>/main.js'] }
            }
        },
        copy: {
            main:{
                expand: true,
                cwd: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/',
                src: '*',
                dest: '<%= meta.fonts_dest %>'
            },
            assets:{
                expand: true,
                cvd: '/assets/images/',
                src: '**',
                dest: 'dist/styles/images'
            }
        },
        watch: {
            sass: {
                files: ['<%= meta.sass_assets_dir %>/**/*.scss'],
                tasks: ['sass']
            },
            lint: {
                files: '<%= jshint.all %>',
                tasks: ['jshint','browserify']
            },
            copy_assets: {
                files: "<%= copy.assets.cvd %>/**",
                task: ['copy:assets']
            }
        }
    });

    // Load tasks
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    //grunt.loadNpmTasks('grunt-contrib-uglify');

    // // Default task(s)
    //grunt.registerTask('test', ['jshint']);
    grunt.registerTask('build', ['sass', 'cssmin', 'uglify', 'copy']);
    grunt.registerTask('default', ['test', 'build']);
};<commit_msg>Fix grunt build task<commit_after>/*global module:false*/

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        meta: {
            css_banner: '/*\n' +
            'Theme Name: Rizikove kaceni teplice based on Sage base wordpress theme' +
            'Author: Jakub Adler\n' +
            '*/\n',
            sass_assets_dir:    'assets/styles',
            js_assets_dir:      'assets/scripts',
            css_dest:           'dist/styles/main.css',
            js_dest:            'dist/scripts/main.js',
            fonts_dest:         'dist/fonts/'
        },
        sass: {
            options:{
              lineNumbers: true
            },
            main: {
                files: {
                   '<%= meta.css_dest %>': '<%= meta.sass_assets_dir %>/main.scss'
                }
            }
        },
        cssmin: {
            main: {
                options: {
                    banner: '<%= meta.css_banner %>'
                },
                files: {
                    '<%= meta.css_dest %>': '<%= meta.css_dest %>'
                }
            }
        },
        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                boss: true,
                eqnull: true,
                browser: true,
                globals: {
                    // jQuery
                    jQuery: true,
                    // extras
                    alert: true,
                    console: true,
                    require: true,
                    $: true,
                    module: true,
                    _ : true,
                    google: true
                }
            },
            all: [
                'Gruntfile.js',
                '<%= meta.js_assets_dir %>/**/*.js'
            ]
        },
        browserify: {
            "app": {
                files: { '<%= meta.js_dest %>': ['<%= meta.js_assets_dir %>/main.js'] }
            }
        },
        uglify: {
            main: {
                files: { '<%= meta.js_dest %>': '<%= meta.js_dest %>' }
            }
        },
        copy: {
            main:{
                expand: true,
                cwd: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/',
                src: '*',
                dest: '<%= meta.fonts_dest %>'
            },
            assets:{
                expand: true,
                cwd: 'assets/images/',
                src: '*',
                dest: 'dist/styles/images/'
            }
        },
        watch: {
            sass: {
                files: ['<%= meta.sass_assets_dir %>/**/*.scss'],
                tasks: ['sass']
            },
            lint: {
                files: '<%= jshint.all %>',
                tasks: ['jshint','browserify']
            },
            copy_assets: {
                files: "<%= copy.assets.cvd %>/**",
                task: ['copy:assets']
            }
        }
    });

    // Load tasks
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-browserify');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    // // Default task(s)
    //grunt.registerTask('test', ['jshint']);
    grunt.registerTask('build', ['sass', 'cssmin', 'browserify', 'uglify', 'copy']);
    grunt.registerTask('default', ['test', 'build']);
};<|endoftext|>


<commit_before>Ext.define('devilry_subjectadmin.view.managestudents.HelpPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.managestudents_help',
    cls: 'bootstrap',

    tpl: [
        '
', gettext('Help'), '
',

        '
', gettext('Groups'), '
',
        '
',
            '', gettext('IMPORTANT'), ': ',
            gettext('{Students_term} are always in a group.'),
            ' ',
            gettext('Even when {students_term} make individual deliveries, they are organized into groups. Each student is added to their own group when you add them to an assignment. This means that the list to your left is all groups registered on this assignment.'),
            '',
        '
',

        '
', gettext('How to create project groups'), '
',
        '
',
            gettext('Select two or more groups, and choose Create project group.'),
        '
',
        '
',
            '',
                gettext('TIP'),
            ': ',
            gettext('Use Select by search to efficiently select students.'),
        '
',

        '
', gettext('Examiners'), '
',
        '
',
            '', gettext('IMPORTANT'), ': ',
            gettext('You are administrator, which is NOT the same as examiner.'),
            ' ',
                gettext('If you want to provide feedback to some groups, you have to make yourself examiner on those groups.'),
            '',
        '
',

        '
',
        '
',

        '
', gettext('How to set {examiners_term}'), '
',
        '
',
            gettext('To set {examiners_term} on a single group, select the group and use the edit button in the {examiner_term} heading on your right hand side.'),
        '
',
        '
',
            gettext('To set {examiners_term} on multiple groups, select the groups and use the buttons in the Manage {examiners_term} section.'),
        '
',

        '
', gettext('Find/select efficiently'), '
',
        '
',
            gettext('Selecting students from the list using the checkboxes works if you have few students. For huge {subjects_term}, manual selection is rarely useful.'),
        '
',
        '
', gettext('Select by pre-defined filters'), '
',
        '
',
            gettext('The Select-button in the lower left corner lets you select groups using a good set of pre-defined filters.'),
        '
',
        '
', gettext('Select by search'), '
',
        '
',
            gettext('The search field at the bottom of the top of the group-list allows you to search for groups. The results is displayed in a menu, and when you select a group from the menu, the group is selected.'),
        '
',

        '
', gettext('Using a small or huge display?'), '
',
        '
',
            gettext('The width of the group-list, and the height of the Summary of selected groups panel (when multiple groups are selected), is not perfect for all displays. To amend this, we allow you to resize these panels. Move your cursor over the inner border of one of these lists, and a resize-indicator will apear. Your selected sizes is saved as a cookie in your browser, which means that they will be remembered when you return to this view in your current browser.'),
        '
'
    ],

    data: {
        Students_term: gettext('Students'),
        students_term: gettext('students'),
        examiners_term: gettext('examiners'),
        subjects_term: gettext('subjects')
    }
});
<commit_msg>subjectadmin...managestudents.HelpPanel: Cleanup terms.<commit_after>Ext.define('devilry_subjectadmin.view.managestudents.HelpPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.managestudents_help',
    cls: 'bootstrap',

    html: [
        '
', gettext('Help'), '
',

        '
', gettext('Groups'), '
',
        '
',
            '', gettext('IMPORTANT'), ': ',
            gettext('Students are always in a group.'),
            ' ',
            gettext('Even when students make individual deliveries, they are organized into groups. Each student is added to their own group when you add them to an assignment. This means that the list to your left is all groups registered on this assignment.'),
            '',
        '
',

        '
', gettext('How to create project groups'), '
',
        '
',
            gettext('Select two or more groups, and choose Create project group.'),
        '
',
        '
',
            '',
                gettext('TIP'),
            ': ',
            gettext('Use Select by search to efficiently select students.'),
        '
',

        '
', gettext('Examiners'), '
',
        '
',
            '', gettext('IMPORTANT'), ': ',
            gettext('You are administrator, which is NOT the same as examiner.'),
            ' ',
                gettext('If you want to provide feedback to some groups, you have to make yourself examiner on those groups.'),
            '',
        '
',

        '
',
        '
',

        '
', gettext('How to set examiners'), '
',
        '
',
            gettext('To set examiners on a single group, select the group and use the edit button in the examiner heading on your right hand side.'),
        '
',
        '
',
            gettext('To set examiners on multiple groups, select the groups and use the buttons in the Manage examiners section.'),
        '
',

        '
', gettext('Find/select efficiently'), '
',
        '
',
            gettext('Selecting students from the list using the checkboxes works if you have few students. For huge subjects, manual selection is rarely useful.'),
        '
',
        '
', gettext('Select by pre-defined filters'), '
',
        '
',
            gettext('The Select-button in the lower left corner lets you select groups using a good set of pre-defined filters.'),
        '
',
        '
', gettext('Select by search'), '
',
        '
',
            gettext('The search field at the bottom of the top of the group-list allows you to search for groups. The results is displayed in a menu, and when you select a group from the menu, the group is selected.'),
        '
',

        '
', gettext('Using a small or huge display?'), '
',
        '
',
            gettext('The width of the group-list, and the height of the Summary of selected groups panel (when multiple groups are selected), is not perfect for all displays. To amend this, we allow you to resize these panels. Move your cursor over the inner border of one of these lists, and a resize-indicator will apear. Your selected sizes is saved as a cookie in your browser, which means that they will be remembered when you return to this view in your current browser.'),
        '
'
    ].join('')
});
<|endoftext|>


<commit_before>Ext.namespace('Gemma');

/**
 * Display experimental factors, allow editing.
 *
 * @class Gemma.ExperimentalFactorGrid
 * @extends Gemma.GemmaGridPanel
 */
Gemma.ExperimentalFactorGrid = Ext.extend(Gemma.GemmaGridPanel, {

			sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
			loadMask : true,

			record : Ext.data.Record.create([{
						name : "id",
						type : "int"
					}, {
						name : "name",
						type : "string"
					}, {
						name : "description",
						type : "string"
					}, {
						name : "category",
						type : "string"
					}, {
						name : "categoryUri",
						type : "string"
					}, {
						name : 'type',
						type : 'string'
					}]),

			categoryStyler : function(value, metadata, record, row, col, ds) {
				return Gemma.GemmaGridPanel.formatTermWithStyle(value, record.get("categoryUri"));
			},

			initComponent : function() {

				this.experimentalDesign = {
					id : this.edId,
					classDelegatingFor : "ExperimentalDesign"
				};

				Ext.apply(this, {
							columns : [{
										header : "Name",
										dataIndex : "name",
										sortable : true
									}, {
										header : "Category",
										dataIndex : "category",
										renderer : this.categoryStyler,
										sortable : true

									}, {
										header : "Description",
										dataIndex : "description",
										sortable : true
									}, {
										header : "Type",
										dataIndex : 'type'
									}]
						});

				this.store = new Ext.data.Store({
							proxy : new Ext.data.DWRProxy(ExperimentalDesignController.getExperimentalFactors),
							reader : new Ext.data.ListRangeReader({
										id : "id"
									}, this.record)
						});

				if (this.editable) {
					this.tbar = new Gemma.ExperimentalFactorToolbar({
						store : this.store
							// used for validation.
						});
				}

				Gemma.ExperimentalFactorGrid.superclass.initComponent.call(this);

				this.addEvents('experimentalfactorchange', 'experimentalfactorselected');

				this.getSelectionModel().on("selectionchange", function(model) {
							var selected = model.getSelections();
							if (selected.length == 1) {
								this.fireEvent("experimentalfactorselected", selected[0].data);
							}

						}.createDelegate(this));

				this.store.load({
							params : [this.experimentalDesign]
						});

			},

			onRender : function(c, l) {

				Gemma.ExperimentalFactorGrid.superclass.onRender.call(this, c, l);

				var NAME_COLUMN = 0;
				var CATEGORY_COLUMN = 1;
				var DESCRIPTION_COLUMN = 2;
				var TYPE_COLUMN = 3;

				this.autoExpandColumn = DESCRIPTION_COLUMN;

				this.nameField = new Ext.form.TextField({});
				var nameEditor = new Ext.grid.GridEditor(this.nameField);

				this.categoryCombo = new Gemma.MGEDCombo({
							lazyRender : true,
							termKey : "factor"
						});

				this.descriptionField = new Ext.form.TextField({
							allowBlank : false
						});

				if (this.editable) {

					var categoryEditor = new Ext.grid.GridEditor(this.categoryCombo);
					this.categoryCombo.on("select", function(combo, record, index) {
								categoryEditor.completeEdit();
							});

					var descriptionEditor = new Ext.grid.GridEditor(this.descriptionField);

					this.factorTypeCombo = new Ext.form.ComboBox({
								triggerAction : 'all',
								lazyRender : true,
								width : 120,
								mode : 'local',
								store : new Ext.data.ArrayStore({
											id : 0,
											fields : ['type', 'display'],
											data : [['continuous', 'continuous'], ['categorical', 'categorical']]
										}),
								valueField : 'type',
								displayField : 'display'
							});

					var typeEditor = new Ext.grid.GridEditor(this.factorTypeCombo);

					this.factorTypeCombo.on("select", function(combo, record, index) {
								typeEditor.completeEdit();
							});

					this.getColumnModel().setEditor(NAME_COLUMN, nameEditor);
					this.getColumnModel().setEditor(CATEGORY_COLUMN, categoryEditor);
					this.getColumnModel().setEditor(DESCRIPTION_COLUMN, descriptionEditor);

					this.getColumnModel().setEditor(TYPE_COLUMN, typeEditor);

					this.getTopToolbar().on("create", function(newFactorValue) {
						var oldmsg = this.loadMask.msg;
						this.loadMask.msg = "Creating new experimental factor";
						this.loadMask.show();

						var callback = function() {
							this.factorCreated(newFactorValue);
							this.loadMask.hide();
							this.loadMask.msg = oldmsg;
						}.createDelegate(this);

						var errorHandler = function(er) {
							this.loadMask.hide();
							this.loadMask.msg = oldmsg;
							Ext.Msg.alert("Error", er);

						}.createDelegate(this);

						ExperimentalDesignController.createExperimentalFactor(this.experimentalDesign, newFactorValue,
								{
									callback : callback,
									errorHandler : errorHandler
								});
					}.createDelegate(this));

					this.getTopToolbar().on("delete", function() {
								var selected = this.getSelectedIds();
								var oldmsg = this.loadMask.msg;
								this.loadMask.msg = "Deleting experimental factor(s)";
								this.loadMask.show();

								var callback = function() {
									this.idsDeleted(selected);
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
								}.createDelegate(this);

								var errorHandler = function(er) {
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
									Ext.Msg.alert("Error", er);
								}.createDelegate(this);

								ExperimentalDesignController.deleteExperimentalFactors(this.experimentalDesign,
										selected, {
											callback : callback,
											errorHandler : errorHandler
										});
							}.createDelegate(this));

					this.getTopToolbar().on("save", function() {
								var edited = this.getEditedRecords();
								var oldmsg = this.loadMask.msg;
								this.loadMask.msg = "Saving ...";
								this.loadMask.show();
								var callback = function() {
									this.recordsChanged(edited);
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
								}.createDelegate(this);

								var errorHandler = function(er) {
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
									Ext.Msg.alert("Error", er);
								}.createDelegate(this);

								ExperimentalDesignController.updateExperimentalFactors(edited, callback);
							}.createDelegate(this));

					this.getTopToolbar().on("undo", this.revertSelected.createDelegate(this));

					this.on("afteredit", function(e) {
								var col = this.getColumnModel().getColumnId(e.column);
								if (col == CATEGORY_COLUMN) {
									var f = this.categoryCombo.getTerm.bind(this.categoryCombo);
									var term = f();
									e.record.set("category", term.term);
									e.record.set("categoryUri", term.uri);
								}
							}.createDelegate(this));

					this.on("afteredit", function(model) {
								this.saveButton.enable();
								this.revertButton.enable();
							}, this.getTopToolbar());

					this.getSelectionModel().on("selectionchange", function(model) {
						if (model) {
							var selected = model.getSelections();
							if (selected.length > 0) {
								this.deleteButton.enable();
							} else {
								this.deleteButton.disable();
							}
							this.revertButton.disable();
							for (var i = 0; i < selected.length; ++i) {
								if (selected[i].dirty) {
									this.revertButton.enable();
									break;
								}
							}
						}
							}, this.getTopToolbar());
				} // if editable.
			},

			factorCreated : function(factor) {
				this.refresh();
				this.fireEvent('experimentalfactorselected', factor);
			},

			recordsChanged : function(records) {
				this.refresh();
				var efs = [];
				for (var i = 0; i < records.length; ++i) {
					efs.push(records[i].data);
				}
				var selModel = this.getSelectionModel();
				var selected = (selModel.hasSelection())? selModel.getSelected() : selModel.selectFirstRow().getSelected();
				this.fireEvent('experimentalfactorchange', this, efs, selected);
			},

			idsDeleted : function(ids) {
				this.refresh();
				var efs = [];
				for (var i = 0; i < ids.length; ++i) {
					efs.push(this.store.getById(ids[i]).data);
				}
				this.fireEvent('experimentalfactorchange', this, efs);
			}

		});

/**
 * Accept entry of data for a new factor, including category and whether it is a continuous variable.
 *
 * @class Gemma.ExperimentalFactorAddWindow
 * @extends Ext.Window
 */
Gemma.ExperimentalFactorAddWindow = Ext.extend(Ext.Window, {

	modal : true,
	closeAction : 'close',
	title : "Fill in new factor details",
	width : 400,

	initComponent : function() {

		Ext.apply(this, {
			items : [{
				xtype : 'form',
				width : 400,
				bodyStyle : "padding:10px",
				monitorValid : true,
				id : 'factor-create-form',
				items : [new Gemma.MGEDCombo({
									id : 'factor-mged-combo',
									emptyText : "Select a category",
									fieldLabel : "Category",
									allowBlank : false,
									termKey : "factor"
								}), {
							xtype : 'textfield',
							width : 250,
							id : 'factor-description-field',
							allowBlank : false,
							fieldLabel : "Description",
							validator : function(value) {
								return this.store.findExact('description', value) < 0 ? true
										: "Description must be unique among factors";
							}.createDelegate(this),
							emptyText : "A short phrase such as 'control vs. drug'"
						}, {
							xtype : 'checkbox',
							id : 'factor-type-checkbox',
							fieldLabel : 'Continuous',
							tooltip : "Check if the factor is a measurement that can take arbitrary numerical values. If in doubt leave this unchecked."
						}]
			}],
			buttons : [{
						text : "Create",
						id : 'factor-create-button',
						tooltip : "Create the new experimental factor",
						disabled : true,
						handler : function() {
							this.fireEvent("done", this.getExperimentalFactorValueObject());
							this.close();
						},
						scope : this
					}, {
						text : "Cancel",
						handler : function() {
							this.close();
						},
						scope : this
					}]
		});

		Gemma.ExperimentalFactorAddWindow.superclass.initComponent.call(this);

		this.addEvents("done");

		Ext.getCmp('factor-create-form').on('clientvalidation', function(form, valid) {
					if (valid) {
						Ext.getCmp('factor-create-button').enable();
					} else {
						Ext.getCmp('factor-create-button').disable();
					}
				});
	},

	getExperimentalFactorValueObject : function() {
		var category = Ext.getCmp('factor-mged-combo').getTerm();
		var description = Ext.getCmp('factor-description-field').getValue();
		return {
			name : category.term,
			description : description,
			category : category.term,
			categoryUri : category.uri,
			type : Ext.getCmp('factor-type-checkbox').getValue() ? "continuous" : "categorical"
		};
	}
});

Gemma.ExperimentalFactorToolbar = Ext.extend(Ext.Toolbar, {

			onRender : function(c, l) {
				Gemma.ExperimentalFactorToolbar.superclass.onRender.call(this, c, l);

				this.createButton = new Ext.Toolbar.Button({
							text : "Add new",
							tooltip : "Add a new experimental factor to the design",
							disabled : false,
							handler : function() {
								var w = new Gemma.ExperimentalFactorAddWindow({
											store : this.store
										});
								w.on('done', function(object) {
											this.fireEvent('create', object);
										}.createDelegate(this));
								w.show();
							},
							scope : this
						});

				this.deleteButton = new Ext.Toolbar.Button({
							text : "Delete",
							tooltip : "Delete the selected experimental factor(s)",
							disabled : true,
							handler : function() {
								Ext.Msg
						.confirm(
								'Deleting records',
								'Are you sure? This cannot be undone. Any associated differential expression analyses will be deleted as well.',
										function(but) {
											if (but == 'yes') {
												this.deleteButton.disable();
												this.fireEvent("delete");
											}
										}.createDelegate(this));

							},
							scope : this
						});

				this.revertButton = new Ext.Toolbar.Button({
							text : "Undo",
							tooltip : "Undo changes to the selected experimental factors",
							disabled : true,
							handler : function() {
								this.fireEvent("undo");
							},
							scope : this
						});

				this.saveButton = new Ext.Toolbar.Button({
							text : "Save",
							tooltip : "Commit changes",
							disabled : true,
							handler : function() {
								this.saveButton.disable();
								this.revertButton.disable();
								this.fireEvent("save");
							},
							scope : this
						});

				this.addButton(this.createButton);
				this.addSeparator();
				this.addButton(this.deleteButton);
				this.addSeparator();
				this.addButton(this.saveButton);
				this.addSeparator();
				this.addButton(this.revertButton);

			},

			initComponent : function() {
				Gemma.ExperimentalFactorToolbar.superclass.initComponent.call(this);
				this.addEvents("create", "save", "undo", "delete");
			}

		});<commit_msg>Moved model selection back to GemmaGrid<commit_after>Ext.namespace('Gemma');

/**
 * Display experimental factors, allow editing.
 *
 * @class Gemma.ExperimentalFactorGrid
 * @extends Gemma.GemmaGridPanel
 */
Gemma.ExperimentalFactorGrid = Ext.extend(Gemma.GemmaGridPanel, {

			loadMask : true,

			record : Ext.data.Record.create([{
						name : "id",
						type : "int"
					}, {
						name : "name",
						type : "string"
					}, {
						name : "description",
						type : "string"
					}, {
						name : "category",
						type : "string"
					}, {
						name : "categoryUri",
						type : "string"
					}, {
						name : 'type',
						type : 'string'
					}]),

			categoryStyler : function(value, metadata, record, row, col, ds) {
				return Gemma.GemmaGridPanel.formatTermWithStyle(value, record.get("categoryUri"));
			},

			initComponent : function() {

				this.experimentalDesign = {
					id : this.edId,
					classDelegatingFor : "ExperimentalDesign"
				};

				Ext.apply(this, {
							columns : [{
										header : "Name",
										dataIndex : "name",
										sortable : true
									}, {
										header : "Category",
										dataIndex : "category",
										renderer : this.categoryStyler,
										sortable : true

									}, {
										header : "Description",
										dataIndex : "description",
										sortable : true
									}, {
										header : "Type",
										dataIndex : 'type'
									}]
						});

				this.store = new Ext.data.Store({
							proxy : new Ext.data.DWRProxy(ExperimentalDesignController.getExperimentalFactors),
							reader : new Ext.data.ListRangeReader({
										id : "id"
									}, this.record)
						});

				if (this.editable) {
					this.tbar = new Gemma.ExperimentalFactorToolbar({
						store : this.store
							// used for validation.
						});
				}

				Gemma.ExperimentalFactorGrid.superclass.initComponent.call(this);

				this.addEvents('experimentalfactorchange', 'experimentalfactorselected');

				this.getSelectionModel().on("selectionchange", function(model) {
							var selected = model.getSelections();
							if (selected.length == 1) {
								this.fireEvent("experimentalfactorselected", selected[0].data);
							}

						}.createDelegate(this));

				this.store.load({
							params : [this.experimentalDesign]
						});

			},

			onRender : function(c, l) {

				Gemma.ExperimentalFactorGrid.superclass.onRender.call(this, c, l);

				var NAME_COLUMN = 0;
				var CATEGORY_COLUMN = 1;
				var DESCRIPTION_COLUMN = 2;
				var TYPE_COLUMN = 3;

				this.autoExpandColumn = DESCRIPTION_COLUMN;

				this.nameField = new Ext.form.TextField({});
				var nameEditor = new Ext.grid.GridEditor(this.nameField);

				this.categoryCombo = new Gemma.MGEDCombo({
							lazyRender : true,
							termKey : "factor"
						});

				this.descriptionField = new Ext.form.TextField({
							allowBlank : false
						});

				if (this.editable) {

					var categoryEditor = new Ext.grid.GridEditor(this.categoryCombo);
					this.categoryCombo.on("select", function(combo, record, index) {
								categoryEditor.completeEdit();
							});

					var descriptionEditor = new Ext.grid.GridEditor(this.descriptionField);

					this.factorTypeCombo = new Ext.form.ComboBox({
								triggerAction : 'all',
								lazyRender : true,
								width : 120,
								mode : 'local',
								store : new Ext.data.ArrayStore({
											id : 0,
											fields : ['type', 'display'],
											data : [['continuous', 'continuous'], ['categorical', 'categorical']]
										}),
								valueField : 'type',
								displayField : 'display'
							});

					var typeEditor = new Ext.grid.GridEditor(this.factorTypeCombo);

					this.factorTypeCombo.on("select", function(combo, record, index) {
								typeEditor.completeEdit();
							});

					this.getColumnModel().setEditor(NAME_COLUMN, nameEditor);
					this.getColumnModel().setEditor(CATEGORY_COLUMN, categoryEditor);
					this.getColumnModel().setEditor(DESCRIPTION_COLUMN, descriptionEditor);

					this.getColumnModel().setEditor(TYPE_COLUMN, typeEditor);

					this.getTopToolbar().on("create", function(newFactorValue) {
						var oldmsg = this.loadMask.msg;
						this.loadMask.msg = "Creating new experimental factor";
						this.loadMask.show();

						var callback = function() {
							this.factorCreated(newFactorValue);
							this.loadMask.hide();
							this.loadMask.msg = oldmsg;
						}.createDelegate(this);

						var errorHandler = function(er) {
							this.loadMask.hide();
							this.loadMask.msg = oldmsg;
							Ext.Msg.alert("Error", er);

						}.createDelegate(this);

						ExperimentalDesignController.createExperimentalFactor(this.experimentalDesign, newFactorValue,
								{
									callback : callback,
									errorHandler : errorHandler
								});
					}.createDelegate(this));

					this.getTopToolbar().on("delete", function() {
								var selected = this.getSelectedIds();
								var oldmsg = this.loadMask.msg;
								this.loadMask.msg = "Deleting experimental factor(s)";
								this.loadMask.show();

								var callback = function() {
									this.idsDeleted(selected);
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
								}.createDelegate(this);

								var errorHandler = function(er) {
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
									Ext.Msg.alert("Error", er);
								}.createDelegate(this);

								ExperimentalDesignController.deleteExperimentalFactors(this.experimentalDesign,
										selected, {
											callback : callback,
											errorHandler : errorHandler
										});
							}.createDelegate(this));

					this.getTopToolbar().on("save", function() {
								var edited = this.getEditedRecords();
								var oldmsg = this.loadMask.msg;
								this.loadMask.msg = "Saving ...";
								this.loadMask.show();
								var callback = function() {
									this.recordsChanged(edited);
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
								}.createDelegate(this);

								var errorHandler = function(er) {
									this.loadMask.hide();
									this.loadMask.msg = oldmsg;
									Ext.Msg.alert("Error", er);
								}.createDelegate(this);

								ExperimentalDesignController.updateExperimentalFactors(edited, callback);
							}.createDelegate(this));

					this.getTopToolbar().on("undo", this.revertSelected.createDelegate(this));

					this.on("afteredit", function(e) {
								var col = this.getColumnModel().getColumnId(e.column);
								if (col == CATEGORY_COLUMN) {
									var f = this.categoryCombo.getTerm.bind(this.categoryCombo);
									var term = f();
									e.record.set("category", term.term);
									e.record.set("categoryUri", term.uri);
								}
							}.createDelegate(this));

					this.on("afteredit", function(model) {
								this.saveButton.enable();
								this.revertButton.enable();
							}, this.getTopToolbar());

					this.getSelectionModel().on("selectionchange", function(model) {
						if (model) {
							var selected = model.getSelections();
							if (selected.length > 0) {
								this.deleteButton.enable();
							} else {
								this.deleteButton.disable();
							}
							this.revertButton.disable();
							for (var i = 0; i < selected.length; ++i) {
								if (selected[i].dirty) {
									this.revertButton.enable();
									break;
								}
							}
						}
							}, this.getTopToolbar());
				} // if editable.
			},

			factorCreated : function(factor) {
				this.refresh();
				this.fireEvent('experimentalfactorselected', factor);
			},

			recordsChanged : function(records) {
				this.refresh();
				var efs = [];
				for (var i = 0; i < records.length; ++i) {
					efs.push(records[i].data);
				}
				var selModel = this.getSelectionModel();
				var selected = (selModel.hasSelection())? selModel.getSelected() : selModel.selectFirstRow().getSelected();
				this.fireEvent('experimentalfactorchange', this, efs, selected);
			},

			idsDeleted : function(ids) {
				this.refresh();
				var efs = [];
				for (var i = 0; i < ids.length; ++i) {
					efs.push(this.store.getById(ids[i]).data);
				}
				this.fireEvent('experimentalfactorchange', this, efs);
			}

		});

/**
 * Accept entry of data for a new factor, including category and whether it is a continuous variable.
 *
 * @class Gemma.ExperimentalFactorAddWindow
 * @extends Ext.Window
 */
Gemma.ExperimentalFactorAddWindow = Ext.extend(Ext.Window, {

	modal : true,
	closeAction : 'close',
	title : "Fill in new factor details",
	width : 400,

	initComponent : function() {

		Ext.apply(this, {
			items : [{
				xtype : 'form',
				width : 400,
				bodyStyle : "padding:10px",
				monitorValid : true,
				id : 'factor-create-form',
				items : [new Gemma.MGEDCombo({
									id : 'factor-mged-combo',
									emptyText : "Select a category",
									fieldLabel : "Category",
									allowBlank : false,
									termKey : "factor"
								}), {
							xtype : 'textfield',
							width : 250,
							id : 'factor-description-field',
							allowBlank : false,
							fieldLabel : "Description",
							validator : function(value) {
								return this.store.findExact('description', value) < 0 ? true
										: "Description must be unique among factors";
							}.createDelegate(this),
							emptyText : "A short phrase such as 'control vs. drug'"
						}, {
							xtype : 'checkbox',
							id : 'factor-type-checkbox',
							fieldLabel : 'Continuous',
							tooltip : "Check if the factor is a measurement that can take arbitrary numerical values. If in doubt leave this unchecked."
						}]
			}],
			buttons : [{
						text : "Create",
						id : 'factor-create-button',
						tooltip : "Create the new experimental factor",
						disabled : true,
						handler : function() {
							this.fireEvent("done", this.getExperimentalFactorValueObject());
							this.close();
						},
						scope : this
					}, {
						text : "Cancel",
						handler : function() {
							this.close();
						},
						scope : this
					}]
		});

		Gemma.ExperimentalFactorAddWindow.superclass.initComponent.call(this);

		this.addEvents("done");

		Ext.getCmp('factor-create-form').on('clientvalidation', function(form, valid) {
					if (valid) {
						Ext.getCmp('factor-create-button').enable();
					} else {
						Ext.getCmp('factor-create-button').disable();
					}
				});
	},

	getExperimentalFactorValueObject : function() {
		var category = Ext.getCmp('factor-mged-combo').getTerm();
		var description = Ext.getCmp('factor-description-field').getValue();
		return {
			name : category.term,
			description : description,
			category : category.term,
			categoryUri : category.uri,
			type : Ext.getCmp('factor-type-checkbox').getValue() ? "continuous" : "categorical"
		};
	}
});

Gemma.ExperimentalFactorToolbar = Ext.extend(Ext.Toolbar, {

			onRender : function(c, l) {
				Gemma.ExperimentalFactorToolbar.superclass.onRender.call(this, c, l);

				this.createButton = new Ext.Toolbar.Button({
							text : "Add new",
							tooltip : "Add a new experimental factor to the design",
							disabled : false,
							handler : function() {
								var w = new Gemma.ExperimentalFactorAddWindow({
											store : this.store
										});
								w.on('done', function(object) {
											this.fireEvent('create', object);
										}.createDelegate(this));
								w.show();
							},
							scope : this
						});

				this.deleteButton = new Ext.Toolbar.Button({
							text : "Delete",
							tooltip : "Delete the selected experimental factor(s)",
							disabled : true,
							handler : function() {
								Ext.Msg
						.confirm(
								'Deleting records',
								'Are you sure? This cannot be undone. Any associated differential expression analyses will be deleted as well.',
										function(but) {
											if (but == 'yes') {
												this.deleteButton.disable();
												this.fireEvent("delete");
											}
										}.createDelegate(this));

							},
							scope : this
						});

				this.revertButton = new Ext.Toolbar.Button({
							text : "Undo",
							tooltip : "Undo changes to the selected experimental factors",
							disabled : true,
							handler : function() {
								this.fireEvent("undo");
							},
							scope : this
						});

				this.saveButton = new Ext.Toolbar.Button({
							text : "Save",
							tooltip : "Commit changes",
							disabled : true,
							handler : function() {
								this.saveButton.disable();
								this.revertButton.disable();
								this.fireEvent("save");
							},
							scope : this
						});

				this.addButton(this.createButton);
				this.addSeparator();
				this.addButton(this.deleteButton);
				this.addSeparator();
				this.addButton(this.saveButton);
				this.addSeparator();
				this.addButton(this.revertButton);

			},

			initComponent : function() {
				Gemma.ExperimentalFactorToolbar.superclass.initComponent.call(this);
				this.addEvents("create", "save", "undo", "delete");
			}

		});<|endoftext|>


<commit_before>function getDepart() {
  return zone0.id;
}

function getArrivee() {
  return zone1.id;
}

var mapWidth = 960.0,
    mapHeight = 500.0,
    centered;

var debug_add_city = false;

var myCenter = [-74.0, 2.5];
var translation = [mapWidth / 2.0, mapHeight / 2.0];
var scale = 2000.0;

var BASE_FONT = "'Helvetica Neue', Helvetica, Arial, sans-serif";

var FONTS = [
  "Open Sans",
  "Josefin Slab",
  "Arvo",
  "Lato",
  "Vollkorn",
  "Abril Fatface",
  "Old StandardTT",
  "Droid+Sans",
  "Lobster",
  "Inconsolata",
  "Montserrat",
  "Playfair Display",
  "Karla",
  "Alegreya",
  "Libre Baskerville",
  "Merriweather",
  "Lora",
  "Archivo Narrow",
  "Neuton",
  "Signika",
  "Questrial",
  "Fjalla One",
  "Bitter",
  "Varela Round"
];
var cities = [
  ["Nantes", 546, 241],
  ["Pornic", 402, 272],
  ["Guérande", 325, 205],
  ["Ancenis", 661, 177],
  ["Chateaubriant", 585, 39]
];
var cities = [
  ["Nantes", -72.10923927606828, 1.757726606443621],
  ["Pornic", -76.2345354010102, 0.8698843815074411],
  ["Guérande", -78.44042291226388, 2.7882252712886517],
  ["Ancenis", -68.81473195406605, 3.589117734374606],
  ["Chateaubriant", -70.99197157556318, 7.523164981942603]
];

var projection = d3.geo.mercator()
  .scale(scale)
  .center(myCenter)
  .translate([translation[0], translation[1]]);

function invertTransformation(n) {
  return projection.invert(n);
}

// apply translation and scale
for (var i=0; i<cities.length; i++) {
  pos = projection([cities[i][1], cities[i][2]])
  cities[i][1] = pos[0];
  cities[i][2] = pos[1];
}

// Define color scale
var color = d3.scale.linear()
  .domain([1, 20])
  .clamp(true)
  .range(['#6666ff', '#6666ff']);

var path = d3.geo.path()
  .projection(projection);

// Set svg width & height
var svg = d3.select('#carte')
  .attr('width', mapWidth)
  .attr('height', mapHeight);

// Add background
svg.append('rect')
  .attr('class', 'background')
  .attr('width', mapWidth)
  .attr('height', mapHeight)
  .attr('opacity', 0)
  .on('click', clicked);

var g = svg.append('g');

var mapLayer = g.append('g')
  .classed('map-layer', true);

var actualZone = "";
var actualId = "";
var zoneBackgroundSize = [80, 40];
var iconCrossSize = [8, 8];
var zoneState = 0;

var zone0 = {
  text: "",
  id : "",
  element: null,
  location: [100, 200],
  color: 'green',

};

zone0.textElement = g.append('text')
      .classed('big-text', true)
      .style('font-family', defaultFontFamily)
      .style("font-size", "14px")
      .attr('x', zone0.location[0])
      .attr('y', zone0.location[1])
      .attr("unselectable", "on");

var zone1 = {
  text: "",
  id: "",
  element: null,
  location: [100, 230],
  color: 'red',
};

zone1.textElement = g.append('text')
      .classed('big-text', true)
      .style('font-family', defaultFontFamily)
      .style("font-size", "14px")
      .attr('x', zone1.location[0])
      .attr('y', zone1.location[1])
      .attr("unselectable", "on");

var defaultFontFamily = FONTS[0] + ', ' + BASE_FONT;

var cross0Image = svg.append("svg:image")
      .classed('hiddenCross', true)
      .attr('x', zone0.location[0] + zoneBackgroundSize[0] - iconCrossSize[0]/2)
      .attr('y', zone0.location[1] - iconCrossSize[1])
      .attr('width', iconCrossSize[0])
      .attr('height', iconCrossSize[1])
      .attr("xlink:href", "img/map/cross.png");

var cross1Image = svg.append("svg:image")
      .classed('hiddenCross', true)
      .attr('x', zone1.location[0] + zoneBackgroundSize[0] - iconCrossSize[0]/2)
      .attr('y', zone1.location[1] - iconCrossSize[1])
      .attr('width', iconCrossSize[0])
      .attr('height', iconCrossSize[1])
      .attr("xlink:href", "img/map/cross.png");

var bigText = g.append('text')
  .classed('big-text', true)
  .attr('x', 20)
  .attr('y', 45)
  .attr("unselectable", "on");

// Display cities
function displayCities() {
  var fontFamily = FONTS[0] + ', ' + BASE_FONT;
  for (var i=0; i<cities.length; i++) {

    var icon_width = 8;
    var icon_height = 8;

    var text = cities[i][0];
    var city_x = cities[i][1];
    var city_y = cities[i][2];

    svg.append("svg:image")
      .classed('notSelectable', true)
      .attr('x', city_x - icon_width/2)
      .attr('y', city_y - icon_height)
      .attr('width', icon_width)
      .attr('height', icon_height)
      .attr("xlink:href", "img/map/dot.png");

    var text = g.append('text')
      .classed('big-text', true)
      .style('font-family', fontFamily)
      .style("font-size", "14px")
      .text(text)
      .attr("unselectable", "on");

    // determine text size
    var bbox = text.node().getBBox();

    var textWidth = bbox.width;
    var textHeight = bbox.height;

    text.attr('x', city_x - textWidth/2)
      .attr('y', city_y + textHeight)
  }
}

displayCities();

// Load map data
//edgt30_simp32_transformed.geo.json
d3.json('data/map/edgt30.geo.json', function(error, mapData) {
  var features = mapData.features;

  // Update color scale domain based on data
  color.domain([0, d3.max(features, nameLength)]);

  // Draw each province as a path
  mapLayer.selectAll('path')
      .data(features)
    .enter().append('path')
      .attr('d', path)
      .attr('vector-effect', 'non-scaling-stroke')
      .style('fill', fillFn)
      .on('mouseover', mouseover)
      .on('mouseout', mouseout)
      .on('click', clicked);
});

// Get province name
function nameFn(d){
  return d && d.properties ? d.properties.name : null;
}

// Get province name length
function nameLength(d){
  var n = nameFn(d);
  return n ? n.length : 0;
}

// Get province color
function fillFn(d){
  return color(nameLength(d));
}

function clicked(d) {
  // Create city from cliced location
  if (debug_add_city)
    console.log(invertTransformation(d3.mouse(this)));

  if (actualZone.localeCompare("") == 0)
    return;

  switch (zoneState) {
    case 0:
      zone0.text = actualZone;
      zone0.id = actualId;
      zoneState++;
      cross0Image.classed('cross', true).classed('hiddenCross', false);
      cross0Image.on('click', unclicked0);

      // Highlight clicked province
      zone0.element = d3.select(this);
      zone0.element.style('fill', zone0.color);

      if (zone1.text.localeCompare("") != 0) {
        zoneState++;
      }
      break;
    case 1:
      zone1.text = actualZone;
      zone1.id = actualId;
      zoneState++;

      // Highlight clicked province
      zone1.element = d3.select(this);
      zone1.element.style('fill', zone1.color);

      cross1Image.classed('cross', true).classed('hiddenCross', false);;
      cross1Image.on('click', unclicked1)
      break;
  }
}

function unclicked0(d) {
  zone0.text = "";
  zone0.id = "";
  zoneState = 0;
  zone0.element = null;
  zone0.textElement.text("");
  cross0Image.classed('cross', false).classed('hiddenCross', true);
  cross0Image.on('click', null);
  colorMap();
}

function unclicked1(d) {
  zone1.text = "";
  zone1.id = "";
  zoneState = (zoneState < 1) ? zoneState : 1;
  zone1.textElement.text("");
  zone1.element = null;
  cross1Image.classed('cross', false).classed('hiddenCross', true);
  cross1Image.on('click', null);
  colorMap();
}

function mouseover(d){
  // Highlight hovered province
  d3.select(this).style('fill', 'orange');

  // Draw effects
  updateZoneText(d);
}

function mouseout(d){

  d3.select(this).style('fill', function(d) {return centered && d===centered ? '#D5708B' : fillFn(d);});

  updateZoneText("");

  colorMap();
}

function updateZoneText(d) {

  var text = nameFn(d);
  actualZone = text;
  actualId = d.d30;

  var myText, loc;
  switch (zoneState) {
    case 0:
      zone0.text = text;
      myText = zone0.textElement;
      loc = zone0.location;
      break;
    case 1:
      zone1.text = text;
      myText = zone1.textElement;
      loc = zone1.location;
      break;
    default:
      return;
  }

  // Change text
  myText.text(text);

  // Compute text size
  var bbox = myText.node().getBBox();
  var textWidth = bbox.width;

  // Update text to center
  myText.attr('x', loc[0] - textWidth/2);
}

function myTextArt(data) {
  // Use random font
  var fontIndex = 0;
  var fontFamily = FONTS[fontIndex] + ', ' + BASE_FONT;

  x = mapWidth / 2;
  y = mapHeight - 20;

  var text = nameFn(data);

  bigText
    .style('font-family', fontFamily)
    .text(text)
    .style('opacity', 0);

  var bbox = bigText.node().getBBox();

  var textWidth = bbox.width;
  var textHeight = bbox.height;

  bigText.attr('x', x - textWidth/2)
    .attr('y', y);

  bigText.transition()
    .style('opacity', function(d){
      return 1.0;
    })
    .attr("y", y - 10)
    .duration(170)
}

function colorMap() {
  mapLayer.selectAll('path')
    .style('fill', function(d){return centered && d===centered ? '#D5708B' : fillFn(d);});

  if (zone0.element != null) {
    zone0.element.style('fill', zone0.color);
  }
  if (zone1.element != null) {
    zone1.element.style('fill', zone1.color);
  }
}

<commit_msg>[BUG] Correction bug selection<commit_after>function getDepart() {
  return zone0.id;
}

function getArrivee() {
  return zone1.id;
}

var mapWidth = 960.0,
    mapHeight = 500.0,
    centered;

var debug_add_city = false;

var myCenter = [-74.0, 2.5];
var translation = [2 * mapWidth / 3, mapHeight / 2.0];
var scale = 2000.0;

var BASE_FONT = "'Helvetica Neue', Helvetica, Arial, sans-serif";

var FONTS = [
  "Open Sans",
  "Josefin Slab",
  "Arvo",
  "Lato",
  "Vollkorn",
  "Abril Fatface",
  "Old StandardTT",
  "Droid+Sans",
  "Lobster",
  "Inconsolata",
  "Montserrat",
  "Playfair Display",
  "Karla",
  "Alegreya",
  "Libre Baskerville",
  "Merriweather",
  "Lora",
  "Archivo Narrow",
  "Neuton",
  "Signika",
  "Questrial",
  "Fjalla One",
  "Bitter",
  "Varela Round"
];

var cities = [
  ["Nantes", -72.10923927606828, 1.757726606443621],
  ["Pornic", -76.2345354010102, 0.8698843815074411],
  ["Guérande", -78.44042291226388, 2.7882252712886517],
  ["Ancenis", -68.81473195406605, 3.589117734374606],
  ["Chateaubriant", -70.99197157556318, 7.523164981942603]
];

var projection = d3.geo.mercator()
  .scale(scale)
  .center(myCenter)
  .translate([translation[0], translation[1]]);

function invertTransformation(n) {
  return projection.invert(n);
}

// apply translation and scale
for (var i=0; i<cities.length; i++) {
  pos = projection([cities[i][1], cities[i][2]])
  cities[i][1] = pos[0];
  cities[i][2] = pos[1];
}

// Define color scale
var color = d3.scale.linear()
  .domain([1, 20])
  .clamp(true)
  .range(['#6666ff', '#6666ff']);

var path = d3.geo.path()
  .projection(projection);

// Set svg width & height
var svg = d3.select('#carte')
  .attr('width', mapWidth)
  .attr('height', mapHeight);

// Add background
svg.append('rect')
  .attr('class', 'background')
  .attr('width', mapWidth)
  .attr('height', mapHeight)
  .attr('opacity', 0);

var g = svg.append('g');

var mapLayer = g.append('g')
  .classed('map-layer', true);

var actualZone = "";
var actualId = "";
var zoneBackgroundSize = [120, 40];
var iconCrossSize = [8, 8];
var zoneState = 0;

var zone0 = {
  text: "",
  id : "",
  element: null,
  location: [100, 200],
  color: 'green',

};

zone0.textElement = g.append('text')
      .classed('big-text', true)
      .style('font-family', defaultFontFamily)
      .style("font-size", "14px")
      .attr('x', zone0.location[0])
      .attr('y', zone0.location[1])
      .attr("unselectable", "on");

var zone1 = {
  text: "",
  id: "",
  element: null,
  location: [100, 230],
  color: 'red',
};

zone1.textElement = g.append('text')
      .classed('big-text', true)
      .style('font-family', defaultFontFamily)
      .style("font-size", "14px")
      .attr('x', zone1.location[0])
      .attr('y', zone1.location[1])
      .attr("unselectable", "on");

var defaultFontFamily = FONTS[0] + ', ' + BASE_FONT;

var cross0Image = svg.append("svg:image")
      .classed('hiddenCross', true)
      .attr('x', zone0.location[0] + zoneBackgroundSize[0] - iconCrossSize[0]/2)
      .attr('y', zone0.location[1] - iconCrossSize[1])
      .attr('width', iconCrossSize[0])
      .attr('height', iconCrossSize[1])
      .attr("xlink:href", "img/map/cross.png");

var cross1Image = svg.append("svg:image")
      .classed('hiddenCross', true)
      .attr('x', zone1.location[0] + zoneBackgroundSize[0] - iconCrossSize[0]/2)
      .attr('y', zone1.location[1] - iconCrossSize[1])
      .attr('width', iconCrossSize[0])
      .attr('height', iconCrossSize[1])
      .attr("xlink:href", "img/map/cross.png");

var bigText = g.append('text')
  .classed('big-text', true)
  .attr('x', 20)
  .attr('y', 45)
  .attr("unselectable", "on");

// Display cities
function displayCities() {
  var fontFamily = FONTS[0] + ', ' + BASE_FONT;
  for (var i=0; i<cities.length; i++) {

    var icon_width = 8;
    var icon_height = 8;

    var text = cities[i][0];
    var city_x = cities[i][1];
    var city_y = cities[i][2];

    svg.append("svg:image")
      .classed('notSelectable', true)
      .attr('x', city_x - icon_width/2)
      .attr('y', city_y - icon_height)
      .attr('width', icon_width)
      .attr('height', icon_height)
      .attr("xlink:href", "img/map/dot.png");

    var text = g.append('text')
      .classed('big-text', true)
      .style('font-family', fontFamily)
      .style("font-size", "14px")
      .text(text)
      .attr("unselectable", "on");

    // determine text size
    var bbox = text.node().getBBox();

    var textWidth = bbox.width;
    var textHeight = bbox.height;

    text.attr('x', city_x - textWidth/2)
      .attr('y', city_y + textHeight)
  }
}

displayCities();

// Load map data
//edgt30_simp32_transformed.geo.json
d3.json('data/map/edgt30.geo.json', function(error, mapData) {
  var features = mapData.features;

  // Update color scale domain based on data
  color.domain([0, d3.max(features, nameLength)]);

  // Draw each province as a path
  mapLayer.selectAll('path')
      .data(features)
    .enter().append('path')
      .attr('d', path)
      .attr('vector-effect', 'non-scaling-stroke')
      .style('fill', fillFn)
      .on('mouseover', mouseOverMap)
      .on('mouseout', mouseOutMap)
      .on('click', mapClicked);
});

// Get province name
function nameFn(d){
  return d && d.properties ? d.properties.name : null;
}

function idFn(d) {
  return d && d.properties ? d.properties.d30 : null;
}

// Get province name length
function nameLength(d){
  var n = nameFn(d);
  return n ? n.length : 0;
}

// Get province color
function fillFn(d){
  return color(nameLength(d));
}

function mapClicked(d) {
  updateZoneText(d);
  // Create city from cliced location
  if (debug_add_city)
    console.log(invertTransformation(d3.mouse(this)));

  if (actualZone != null && actualZone.localeCompare("") == 0)
    return;

  switch (zoneState) {
    case 0:
      zone0.text = actualZone;
      zone0.id = actualId;
      zoneState++;
      cross0Image.classed('cross', true).classed('hiddenCross', false);
      cross0Image.on('click', unclickedMap0);

      // Highlight clicked province
      zone0.element = d3.select(this);
      zone0.element.style('fill', zone0.color);

      if (zone1.text.localeCompare("") != 0) {
        zoneState++;
      }
      break;
    case 1:
      zone1.text = actualZone;
      zone1.id = actualId;
      zoneState++;

      // Highlight clicked province
      zone1.element = d3.select(this);
      zone1.element.style('fill', zone1.color);

      cross1Image.classed('cross', true).classed('hiddenCross', false);;
      cross1Image.on('click', unclickedMap1)
      break;
  }
}

function unclickedMap0(d) {
  zone0.text = "";
  zone0.id = "";
  zoneState = 0;
  zone0.element = null;
  zone0.textElement.text("");
  cross0Image.classed('cross', false).classed('hiddenCross', true);
  cross0Image.on('click', null);
  colorMap();
}

function unclickedMap1(d) {
  zone1.text = "";
  zone1.id = "";
  zoneState = (zoneState < 1) ? zoneState : 1;
  zone1.textElement.text("");
  zone1.element = null;
  cross1Image.classed('cross', false).classed('hiddenCross', true);
  cross1Image.on('click', null);
  colorMap();
}

function mouseOverMap(d){
  // Highlight hovered province
  d3.select(this).style('fill', 'orange');

  // Draw effects
  updateZoneText(d);
}

function mouseOutMap(d){

  d3.select(this).style('fill', function(d) {return centered && d===centered ? '#D5708B' : fillFn(d);});

  updateZoneText("");

  colorMap();
}

function updateZoneText(d) {

  var text = nameFn(d);
  actualZone = text;
  actualId = idFn(d);

  var myText, loc;
  switch (zoneState) {
    case 0:
      zone0.text = text;
      myText = zone0.textElement;
      loc = zone0.location;
      break;
    case 1:
      zone1.text = text;
      myText = zone1.textElement;
      loc = zone1.location;
      break;
    default:
      return;
  }

  // Change text
  myText.text(text);

  // Compute text size
  var bbox = myText.node().getBBox();
  var textWidth = bbox.width;

  // Update text to center
  myText.attr('x', loc[0] - textWidth/2);
}

function myTextArt(data) {
  // Use random font
  var fontIndex = 0;
  var fontFamily = FONTS[fontIndex] + ', ' + BASE_FONT;

  x = mapWidth / 2;
  y = mapHeight - 20;

  var text = nameFn(data);

  bigText
    .style('font-family', fontFamily)
    .text(text)
    .style('opacity', 0);

  var bbox = bigText.node().getBBox();

  var textWidth = bbox.width;
  var textHeight = bbox.height;

  bigText.attr('x', x - textWidth/2)
    .attr('y', y);

  bigText.transition()
    .style('opacity', function(d){
      return 1.0;
    })
    .attr("y", y - 10)
    .duration(170)
}

function colorMap() {
  mapLayer.selectAll('path')
    .style('fill', function(d){return centered && d===centered ? '#D5708B' : fillFn(d);});

  if (zone0.element != null) {
    zone0.element.style('fill', zone0.color);
  }
  if (zone1.element != null) {
    zone1.element.style('fill', zone1.color);
  }
}

<|endoftext|>


<commit_before>import React from 'react';

import SprkModal from './SprkModal';

export default {
  title: 'Components|Modal',
  component: SprkModal,
};

export const defaultStory = () => (
  <SprkModal
    title="Default Modal"
    isVisible={true}
    confirmText="Confirm Text"
    cancelText="Cancel Text"
    confirmClick={() => {
      alert('confirm');
    }}
    cancelClick={() => {
      alert('cancel click');
    }}
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

defaultStory.story = {
  name: 'Default',
};

export const infoStory = () => (
  <SprkModal
    title="Info Modal"
    isVisible={true}
    variant="info"
    confirmClick={() => {
      alert('confirm click');
    }}
    cancelClick={() => {
      alert('cancel click');
    }}
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

infoStory.story = {
  name: 'Info',
};

defaultStory.story = {
  name: 'Default',
};

export const waitStory = () => (
  <SprkModal
    title="Wait Modal"
    isVisible={true}
    variant="wait"
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

waitStory.story = {
  name: 'Wait',
};
<commit_msg>react formatting<commit_after>import React from 'react';

import SprkModal from './SprkModal';

export default {
  title: 'Components|Modal',
  component: SprkModal,
};

export const defaultStory = () => (
  <SprkModal
    title="Default Modal"
    isVisible={true}
    confirmText="Confirm Text"
    cancelText="Cancel Text"
    confirmClick={() => {
      alert('confirm');
    }}
    cancelClick={() => {
      alert('cancel click');
    }}
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

defaultStory.story = {
  name: 'Default',
};

export const infoStory = () => (
  <SprkModal
    title="Info Modal"
    isVisible={true}
    variant="info"
    confirmClick={() => {
      alert('confirm click');
    }}
    cancelClick={() => {
      alert('cancel click');
    }}
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

infoStory.story = {
  name: 'Info',
};

defaultStory.story = {
  name: 'Default',
};

export const waitStory = () => (
  <SprkModal
    title="Wait Modal"
    isVisible={true}
    variant="wait"
  >
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.
  </SprkModal>
);

waitStory.story = {
  name: 'Wait',
};
<|endoftext|>