<commit_before>var express = require('express');
var event = require('./routes/events');
var sub = require('./routes/subscriptions');
var signal = require('./routes/signals');

var port = (process.env.PORT || 3000);

var app = express();

app.configure(function () {
    app.use(express.logger('dev'));     /* 'default', 'short', 'tiny', 'dev' */
    app.use(express.bodyParser());
});

console.log ('registering event routes with express');
app.get('/events', event.findAll);
app.get('/events/:id', event.findById);
app.post('/events', event.addEvent);
app.put('/events/:id', event.updateEvent);
app.delete('/events/:id', event.deleteEvent);

console.log ('registering subscription routes with express');
app.get('/subscriptions', sub.findAll);
app.get('/subscriptions/:id', sub.findById);
app.post('/subscriptions', sub.addSubscription);
app.put('/subscriptions/:id', sub.updateSubscription);
app.delete('/subscriptions/:id', sub.deleteSubscription);

console.log ('registering signal routes with express');
app.post('/signals', signal.processSignal);

console.log ('About to start listening');
app.listen(3000);
console.log('Listening on port: ', port);<commit_msg>port bug<commit_after>var express = require('express');
var event = require('./routes/events');
var sub = require('./routes/subscriptions');
var signal = require('./routes/signals');

var port = (process.env.PORT || 3000);

var app = express();

app.configure(function () {
    app.use(express.logger('dev'));     /* 'default', 'short', 'tiny', 'dev' */
    app.use(express.bodyParser());
});

console.log ('registering event routes with express');
app.get('/events', event.findAll);
app.get('/events/:id', event.findById);
app.post('/events', event.addEvent);
app.put('/events/:id', event.updateEvent);
app.delete('/events/:id', event.deleteEvent);

console.log ('registering subscription routes with express');
app.get('/subscriptions', sub.findAll);
app.get('/subscriptions/:id', sub.findById);
app.post('/subscriptions', sub.addSubscription);
app.put('/subscriptions/:id', sub.updateSubscription);
app.delete('/subscriptions/:id', sub.deleteSubscription);

console.log ('registering signal routes with express');
app.post('/signals', signal.processSignal);

console.log ('About to start listening');
app.listen(port);
console.log('Listening on port: ', port);<|endoftext|>


<commit_before>document.addEventListener('DOMContentLoaded', function () {

    // Data to load.
    var cats = [
        {
            name: 'Salsa',
            url: 'img/kitten1.jpg',
            counter: 0
        },
        {
            name: 'Pearl',
            url: 'img/koshenka.jpg',
            counter: 0
        },
        {
            name: 'Ebony',
            url: 'img/kitten3.jpg',
            counter: 0
        },
        {
            name: 'Misty',
            url: 'img/kitten4.jpg',
            counter: 0
        },
        {
            name: 'Buttercup',
            url: 'img/kitten5.jpg',
            counter: 0
        },
        {
            name: 'Mocha',
            url: 'img/kitten6.jpg',
            counter: 0
        },
    ];

    // Model.
    var model = {
        init: function () {
            if(!localStorage.notes) {
                localStorage.notes = JSON.stringify(cats);
            }
        },
        getAllKittens: function () {
            return JSON.parse(localStorage.notes);
        },
        getKittenByName: function (name) {
            var kittens = JSON.parse(localStorage.notes);
            var kitten = undefined;
            for (var i = 0; i < kittens.length; i++) {
                if (name === kittens[i].name) {
                    kitten = kittens[i];
                }
            }
            return kitten;
        },
        getAllKittensNames: function () {
            var kittens = JSON.parse(localStorage.notes);
            var names = [];
            for (var i = 0; i < kittens.length; i++) {
                names.push(kittens[i].name);
            }
            return names;
        },
        getFirstKitten: function () {
            var kittens = JSON.parse(localStorage.notes);
            return kittens[0];
        },
        addClick: function (kitten) {
            var kittens = JSON.parse(localStorage.notes);
            kittens.forEach(function (kit) {
               if (kit.name == kitten.name) {
                   kit.counter += 1;
               }
            });
            localStorage.notes = JSON.stringify(kittens);
        }
    };

    // Octopus.
    var octopus = {
        getNames: function () {
            return model.getAllKittensNames();
        },
        getFirstKitten: function () {
            return model.getFirstKitten();
        },
        getKittenByName: function (name) {
            return model.getKittenByName(name);
        },
        changeKitten: function (name) {
            viewKitten.render(octopus.getKittenByName(name));
        },
        addClick: function (kitten) {
            model.addClick(kitten);
            viewKitten.renderCounter(model.getKittenByName(kitten.name));
        },
        init: function () {
            model.init();
            viewMenu.init();
            viewKitten.init();
            viewAdmin.init();
        }
    };

    // View for navigation.
    var viewMenu = {
        init: function () {
            this.menu = document.querySelector('.menu');
            this.render();
        },
        render: function () {
            this.menu.innerHTML = '';
            octopus.getNames().forEach((function (menu) {
                return function (kittenName) {
                    var menu_item = document.createElement('li');
                    menu_item.setAttribute('class', 'kitten');
                    menu_item.textContent = kittenName;
                    menu_item.addEventListener('click', function () {
                        octopus.changeKitten(kittenName);
                    });
                    menu.appendChild(menu_item);
                }
            })(this.menu));
        }
    };

    // View for rendering individual kitten.
    var viewKitten = {
        init: function () {
            this.kittenImageContainer = document.querySelector('.kitten-container .image-container');
            this.kittenName = document.querySelector('.kitten-container h2');
            this.kittenClicks = document.querySelector('.kitten-container span');
            var kitten = octopus.getFirstKitten();
            this.render(kitten);
        },
        render: function (kitten) {
            this.kittenImageContainer.innerHTML = '';
            this.kittenName.textContent = kitten.name;
            var image = document.createElement('img');
            image.setAttribute('src', kitten.url);
            image.addEventListener('click', function () {
                octopus.addClick(kitten);
            });
            this.kittenImageContainer.appendChild(image);
            this.renderCounter(kitten)
        },
        renderCounter: function (kitten) {
            this.kittenClicks.textContent = kitten.counter + ' clicks!';
        }
    };

    // View for admin panel.
    var viewAdmin = {
        init: function () {
            this.panel = document.querySelector('#new-kitten-form');
            this.showPanelBtn = document.querySelector('#show-panel');
            this.isVisible = false;

            // Add event handler for button Admin.
            this.showPanelBtn.addEventListener('click', (
                function (self) {
                    return function (e) {
                        self.isVisible = true;
                        self.render();
                        console.log(self.isVisible);
                        e.preventDefault();
                    }
                }
            )(this));
            this.render();
        },
        render: function () {
            // Show and hide panel
            console.log('From render function. Is visible? ' + this.isVisible);
            if (this.isVisible) {
                this.panel.style.display = 'block';
            }
            else {
                this.panel.style.display = 'none';
            }
        }
    }

    octopus.init();
});<commit_msg>add event handler for cancel button<commit_after>document.addEventListener('DOMContentLoaded', function () {

    // Data to load.
    var cats = [
        {
            name: 'Salsa',
            url: 'img/kitten1.jpg',
            counter: 0
        },
        {
            name: 'Pearl',
            url: 'img/koshenka.jpg',
            counter: 0
        },
        {
            name: 'Ebony',
            url: 'img/kitten3.jpg',
            counter: 0
        },
        {
            name: 'Misty',
            url: 'img/kitten4.jpg',
            counter: 0
        },
        {
            name: 'Buttercup',
            url: 'img/kitten5.jpg',
            counter: 0
        },
        {
            name: 'Mocha',
            url: 'img/kitten6.jpg',
            counter: 0
        },
    ];

    // Model.
    var model = {
        init: function () {
            if(!localStorage.notes) {
                localStorage.notes = JSON.stringify(cats);
            }
        },
        getAllKittens: function () {
            return JSON.parse(localStorage.notes);
        },
        getKittenByName: function (name) {
            var kittens = JSON.parse(localStorage.notes);
            var kitten = undefined;
            for (var i = 0; i < kittens.length; i++) {
                if (name === kittens[i].name) {
                    kitten = kittens[i];
                }
            }
            return kitten;
        },
        getAllKittensNames: function () {
            var kittens = JSON.parse(localStorage.notes);
            var names = [];
            for (var i = 0; i < kittens.length; i++) {
                names.push(kittens[i].name);
            }
            return names;
        },
        getFirstKitten: function () {
            var kittens = JSON.parse(localStorage.notes);
            return kittens[0];
        },
        addClick: function (kitten) {
            var kittens = JSON.parse(localStorage.notes);
            kittens.forEach(function (kit) {
               if (kit.name == kitten.name) {
                   kit.counter += 1;
               }
            });
            localStorage.notes = JSON.stringify(kittens);
        }
    };

    // Octopus.
    var octopus = {
        getNames: function () {
            return model.getAllKittensNames();
        },
        getFirstKitten: function () {
            return model.getFirstKitten();
        },
        getKittenByName: function (name) {
            return model.getKittenByName(name);
        },
        changeKitten: function (name) {
            viewKitten.render(octopus.getKittenByName(name));
        },
        addClick: function (kitten) {
            model.addClick(kitten);
            viewKitten.renderCounter(model.getKittenByName(kitten.name));
        },
        init: function () {
            model.init();
            viewMenu.init();
            viewKitten.init();
            viewAdmin.init();
        }
    };

    // View for navigation.
    var viewMenu = {
        init: function () {
            this.menu = document.querySelector('.menu');
            this.render();
        },
        render: function () {
            this.menu.innerHTML = '';
            octopus.getNames().forEach((function (menu) {
                return function (kittenName) {
                    var menu_item = document.createElement('li');
                    menu_item.setAttribute('class', 'kitten');
                    menu_item.textContent = kittenName;
                    menu_item.addEventListener('click', function () {
                        octopus.changeKitten(kittenName);
                    });
                    menu.appendChild(menu_item);
                }
            })(this.menu));
        }
    };

    // View for rendering individual kitten.
    var viewKitten = {
        init: function () {
            this.kittenImageContainer = document.querySelector('.kitten-container .image-container');
            this.kittenName = document.querySelector('.kitten-container h2');
            this.kittenClicks = document.querySelector('.kitten-container span');
            var kitten = octopus.getFirstKitten();
            this.render(kitten);
        },
        render: function (kitten) {
            this.kittenImageContainer.innerHTML = '';
            this.kittenName.textContent = kitten.name;
            var image = document.createElement('img');
            image.setAttribute('src', kitten.url);
            image.addEventListener('click', function () {
                octopus.addClick(kitten);
            });
            this.kittenImageContainer.appendChild(image);
            this.renderCounter(kitten)
        },
        renderCounter: function (kitten) {
            this.kittenClicks.textContent = kitten.counter + ' clicks!';
        }
    };

    // View for admin panel.
    var viewAdmin = {
        init: function () {
            this.panel = document.querySelector('#new-kitten-form');
            this.showPanelBtn = document.querySelector('#show-panel');
            this.cancelBtn = document.querySelector('#cancel');
            this.saveBtn = document.querySelector('#save');

            this.isVisible = false;

            // Add event handler for button Admin.
            this.showPanelBtn.addEventListener('click', (
                function (self) {
                    return function (e) {
                        self.isVisible = true;
                        self.render();
                    }
                }
            )(this));

            // Add event handler for Cancel button.
            this.cancelBtn.addEventListener('click', (
                function (self) {
                    return function (e) {
                        self.isVisible = false;
                        self.render();
                    }
                })(this));
            this.render();
        },
        render: function () {
            // Show and hide panel
            console.log('From render function. Is visible? ' + this.isVisible);
            if (this.isVisible) {
                this.panel.style.display = 'block';
            }
            else {
                this.panel.style.display = 'none';
            }
        }
    }

    octopus.init();
});<|endoftext|>


<commit_before>var express = require('express'),
  http = require('http'),
  corsMiddleware = require('cors'),
  app = express(),
  master = require('./server/master.js');

var envPort = process.env.PORT || 8001;
var server = app.listen(envPort, function() {
  console.log('Listening on port %d', server.address().port);
});

var io = require('socket.io').listen(server, {
  origins: '*:*'
});

io.on('connection', function(socket) {
  //if existing servers are open..
  socket.emit('hello', {
    stopped: master.isStopped()
  });
  socket.on('hello', function(data) {
    console.log('hello ', data.deviceId);
    if (!data.deviceId) {
      console.error('device attempted to connect without an id');
      return;
    }
    var device = master.matchDevice(data.deviceId, socket);
    if (master.isStopped()) {
      //must match with the device before returning
      return;
    }
    socket.emit('update', {
      moves: master.getMoves(),
      lastMoveHash: device.lastMoveHash
    });
  });
  socket.on('event', function(data) {
    if (master.isStopped()) {
      return;
    }
    console.log('update recieved: ', data.deviceId, data.hash, data.type);
    master.onUpdate(data);
  });
  socket.on('playMove', function(data) {
    console.log('move repeated: ', data.deviceId, data.hash, data.type);
    if (master.isStopped()) {
      return;
    }
    var device = master.matchDevice(data.deviceId, socket);
    if (device) {
      device.lastMoveHash = data.hash;
    }
  });
  socket.on('reset', function(data) {
    if (!data) {
      data = {};
    }
    console.log('reset');
    master.reset(data);
  });
  socket.on('stop', function(data) {
    console.log('stop');
    master.stop();
  });
  socket.on('start', function(data) {
    if (!data) {
      data = {};
    }
    master.reset(data);
  });
});
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Headers",
    'Content-Type, Accept, Origin, Cookie, X-Requested-With,' +
    'X-DevTools-Emulate-Network-Conditions-Client-Id, Access-Control-Request-Headers, Access-Control-Request-Method, Referer'
  );
  res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
  next();
});
app.options('*', function(req, res) {
  res.send(' ');
});

//todo: break these out
app.get('/jquery', function(req, res) {
  res.sendfile(__dirname + '/node_modules/jquery/dist/jquery.js');
});
app.get('/jquery.cookie', function(req, res) {
  res.sendfile(__dirname + '/node_modules/jquery.cookie/jquery.cookie.js');
});
app.get('/socket.js-client', function(req, res) {
  res.sendfile(__dirname + '/node_modules/socket.io-client/socket.io.js');
});
app.get('/helpers', function(req, res) {
  res.sendfile(__dirname + '/client/helpers.js');
});
app.get('/master-command', function(req, res) {
  res.sendfile(__dirname + '/client/master.js');
});<commit_msg>logging/quickly debugging a production issue<commit_after>var express = require('express'),
  http = require('http'),
  corsMiddleware = require('cors'),
  app = express(),
  master = require('./server/master.js');

var envPort = process.env.PORT || 8001;

var server = require('http').createServer(app);
var io = require('socket.io').listen(server, {
  origins: '*:*'
});

var server.listen(envPort, function() {
  console.log('Listening on port %d', server.address().port);
});

io.on('connection', function(socket) {
  //if existing servers are open..
  socket.emit('hello', {
    stopped: master.isStopped()
  });
  socket.on('hello', function(data) {
    console.log('hello ', data.deviceId);
    if (!data.deviceId) {
      console.error('device attempted to connect without an id');
      return;
    }
    var device = master.matchDevice(data.deviceId, socket);
    if (master.isStopped()) {
      //must match with the device before returning
      return;
    }
    socket.emit('update', {
      moves: master.getMoves(),
      lastMoveHash: device.lastMoveHash
    });
  });
  socket.on('event', function(data) {
    if (master.isStopped()) {
      return;
    }
    console.log('update recieved: ', data.deviceId, data.hash, data.type);
    master.onUpdate(data);
  });
  socket.on('playMove', function(data) {
    console.log('move repeated: ', data.deviceId, data.hash, data.type);
    if (master.isStopped()) {
      return;
    }
    var device = master.matchDevice(data.deviceId, socket);
    if (device) {
      device.lastMoveHash = data.hash;
    }
  });
  socket.on('reset', function(data) {
    if (!data) {
      data = {};
    }
    console.log('reset');
    master.reset(data);
  });
  socket.on('stop', function(data) {
    console.log('stop');
    master.stop();
  });
  socket.on('start', function(data) {
    if (!data) {
      data = {};
    }
    master.reset(data);
  });
});
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Headers",
    'Content-Type, Accept, Origin, Cookie, X-Requested-With,' +
    'X-DevTools-Emulate-Network-Conditions-Client-Id, Access-Control-Request-Headers, Access-Control-Request-Method, Referer'
  );
  res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
  next();
});
app.options('*', function(req, res) {
  res.send(' ');
});

//todo: break these out
app.get('/jquery', function(req, res) {
  res.sendfile(__dirname + '/node_modules/jquery/dist/jquery.js');
});
app.get('/jquery.cookie', function(req, res) {
  res.sendfile(__dirname + '/node_modules/jquery.cookie/jquery.cookie.js');
});
app.get('/socket.js-client', function(req, res) {
  res.sendfile(__dirname + '/node_modules/socket.io-client/socket.io.js');
});
app.get('/helpers', function(req, res) {
  res.sendfile(__dirname + '/client/helpers.js');
});
app.get('/master-command', function(req, res) {
  res.sendfile(__dirname + '/client/master.js');
});<|endoftext|>


<commit_before>/*jslint browser: true*/
(function () {
    "use strict";

    var SHOW_CARD_IN_BIG_CLASS_NAME = 'show-in-big',
        CARD_CLASS_NAME = 'card',
        BIG_CARD_CLASS_NAME = 'big-card',
        SMALL_CARD_CLASS_NAME = 'small-card',
        FRONT_CARD_CLASS_NAME = 'front',
        BACK_CARD_CLASS_NAME = 'back',
        CARD_SIDE_CLASS_NAME = 'card-side',
        showing = false,
        placeClickEnabled = true,
        body,
        place;

    function byId(id) {
        return document.getElementById(id);
    }

    function listen(elem, event, cb) {
        elem.addEventListener(event, cb, false);
    }

    function onClick(elem, cb) {
        listen(byId(elem), 'click', cb);
    }

    function isSmallCardElem(elem) {
        var classList = elem.classList;
        return classList &&
                classList.contains(CARD_CLASS_NAME) &&
                !classList.contains(BIG_CARD_CLASS_NAME);
    }

    function getCardElem(elem) {
        var output;

        if (isSmallCardElem(elem)) {
            output = elem;
        } else if (elem.parentNode) {
            output = getCardElem(elem.parentNode);
        } else {
            output = null;
        }

        return output;
    }

    /*jslint eqeq: true*/
    function truthy(elem) {
        return elem != null;
    }
    /*jslint eqeq: false*/

    function hideDisplayedCard() {
        body.classList.remove(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function setData(element) {
        function setElementData(name, value) {
            if (element.dataset) {
                element.dataset[name] = value;
            } else {
                element.setAttribute('data-' + name, value);
            }
        }

        return function (data) {
            setElementData.apply(element, data);
        };
    }

    function getData(element, name) {
        var output;
        if (element.dataset) {
            output = element.dataset[name];
        } else {
            output = element.getAttribute('data-' + name);
        }

        return output;
    }

    function setAttributes(element) {
        return function (attrib) {
            element.setAttribute.apply(element, attrib);
        };
    }

    function fibonacci(test, acc) {
        var val;

        if (acc.length < 2) {
            val = 1;
        } else {
            val = acc[acc.length - 2] + acc[acc.length - 1];
        }

        if (test(val)) {
            acc.push(val);

            return fibonacci(test, acc);
        }

        return acc;
    }

    function processDisplayedValue(value) {
        if (+value === 0.5) {
            value = '1/2';
        } else if (value === 'coffe') {
            value = '';
        } else if (+value === Infinity) {
            value = '∞';
        }
        return String(value);
    }

    function createElement(name, classes, data, attributes, text) {
        var element = document.createElement(name);

        classes.forEach(function (cn) {
            element.classList.add(cn);
        });
        data.forEach(setData(element));
        attributes.forEach(setAttributes(element));

        if (truthy(text)) {
            element.innerHTML = text;
        }

        return element;
    }

    function createDiv(classes, data, attributes, text) {
        return createElement('div', classes, data, attributes, text);
    }

    function createCardSide(element, which, text) {
        var cardSide = createDiv([CARD_SIDE_CLASS_NAME, which], [], [], text);
        element.appendChild(cardSide);
    }

    function createCard(value) {
        var card = createDiv([CARD_CLASS_NAME, SMALL_CARD_CLASS_NAME], [['value', value]], []);

        createCardSide(card, FRONT_CARD_CLASS_NAME, processDisplayedValue(value));
        createCardSide(card, BACK_CARD_CLASS_NAME);

        return card;
    }

    function showDisplayedCard(value) {
        var card = byId('DisplayedCard');

        hideDisplayedCard();

        setTimeout(function () {
            body.classList.add(SHOW_CARD_IN_BIG_CLASS_NAME);
            card.querySelector('.' + FRONT_CARD_CLASS_NAME).innerHTML = processDisplayedValue(value);
        }, 200);
    }

    function toArray(args) {
        return Array.prototype.slice.call(args);
    }

    function removeCard(card) {
        place.removeChild(card);
    }

    function removeCards() {
        var cards = toArray(place.querySelectorAll('.' + CARD_CLASS_NAME + ':not(.' + BIG_CARD_CLASS_NAME + ')'));

        cards.forEach(removeCard);
    }

    function addCards(cards) {
        var fragment = document.createDocumentFragment();

        cards.forEach(function (val) {
            fragment.appendChild(createCard(val));
        });

        place.appendChild(fragment);
    }

    function showClickedCard(cardElem) {
        var value;

        if (cardElem) {
            value = getData(cardElem, 'value');
            showDisplayedCard(value);
        }
    }

    function cardChangeDisabled() {
        return showing || !placeClickEnabled;
    }

    function isBigCardVisible() {
        return body.classList.contains(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function hideBigCard() {
        body.classList.remove(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function onPlaceClick(event) {
        var cardElem;

        event.preventDefault();
        event.stopPropagation();

        if (cardChangeDisabled()) {
            return;
        }

        if (isBigCardVisible()) {
            hideBigCard();
        } else {
            cardElem = getCardElem(event.target);

            if (cardElem) {
                showClickedCard(cardElem);
            }
        }

        showing = true;

        setTimeout(function () {
            showing = false;
        }, 200);
    }

    function disablePlaceClick() {
        placeClickEnabled = false;
    }

    function enablePlaceClick() {
        placeClickEnabled = true;
    }

    function getFibonacciCards() {
        return fibonacci(function (last) {
            return last < 100; // generate fibonacci until last item is less then 100
        }, [0]).reduce(function (prev, current, index, array) {
            var arr = prev || [prev];

            if (arr.indexOf(current) === -1) {
                return arr.concat(current);
            }

            return arr;
        }, ['?', 0.5]);
    }

    function getStandardCards() {
        return ['coffe', '?', 0, 0.5, 1, 2, 3, 5, 8, 13, 20, 40, 100, Infinity];
    }

    function getTshirtCards() {
        return ['XS', 'S', 'M', 'L', 'XL', 'XL', '?'];
    }

    function setActiveCardTypeButton(type) {
        var toolbar = byId('Toolbar');
        if (type === 'standard') {
            toolbar.classList.add('active-standard');
        } else {
            toolbar.classList.remove('active-standard');
        }

        if (type === 'tshirt') {
            toolbar.classList.add('active-tshirt');
        } else {
            toolbar.classList.remove('active-tshirt');
        }

        if (type === 'fibonacci') {
            toolbar.classList.add('active-fibonacci');
        } else {
            toolbar.classList.remove('active-fibonacci');
        }
    }

    function getCards(type) {
        var cards;

        if (type === 'fibonacci') {
            cards = getFibonacciCards();
        } else if (type === 'tshirt') {
            cards = getTshirtCards();
        } else {
            cards = getStandardCards();
        }

        return cards;
    }

    function getSelectCardCb(type) {
        return function () {
            if (cardChangeDisabled()) {
                return;
            }
            removeCards();
            addCards(getCards(type));
            setActiveCardTypeButton(type);
        };
    }

    listen(window, 'load', function () {
        place = byId('PokerPlace');
        body = document.getElementsByTagName('body')[0];

        removeCards();
        addCards(getStandardCards());

        listen(body, 'click', onPlaceClick);
        listen(place, 'click', enablePlaceClick);
        listen(body, 'touchstart', enablePlaceClick);
        listen(body, 'touchmove', disablePlaceClick);
        listen(body, 'touchend', onPlaceClick);

        listen(byId('CardTypeSelectStandard'), 'click', getSelectCardCb('standard'));
        listen(byId('CardTypeSelectTshirt'), 'click', getSelectCardCb('tshirt'));
        listen(byId('CardTypeSelectFibonacci'), 'click', getSelectCardCb('fibonacci'));
        listen(byId('CardTypeSelectStandard'), 'touchend', getSelectCardCb('standard'));
        listen(byId('CardTypeSelectTshirt'), 'touchend', getSelectCardCb('tshirt'));
        listen(byId('CardTypeSelectFibonacci'), 'touchend', getSelectCardCb('fibonacci'));

        listen(byId('DisplayedCard'), 'click', hideDisplayedCard);
    }, false);
}());
<commit_msg>Use onClick and constants<commit_after>/*jslint browser: true*/
(function () {
    'use strict';

    var SHOW_CARD_IN_BIG_CLASS_NAME = 'show-in-big',
        CARD_CLASS_NAME = 'card',
        BIG_CARD_CLASS_NAME = 'big-card',
        SMALL_CARD_CLASS_NAME = 'small-card',
        FRONT_CARD_CLASS_NAME = 'front',
        BACK_CARD_CLASS_NAME = 'back',
        CARD_SIDE_CLASS_NAME = 'card-side',
        DOM_EVENTS = {
            CLICK: 'click',
            TOUCHEND: 'touchend',
            TOUCHMOVE: 'touchmove',
            TOUCHSTART: 'touchstart'
        },
        showing = false,
        placeClickEnabled = true,
        body,
        place;

    function byId(id) {
        return document.getElementById(id);
    }

    function listen(elem, event, cb) {
        elem.addEventListener(event, cb, false);
    }

    function onClick(elem, cb) {
        if (typeof elem === 'string') {
            elem = byId(elem);
        }
        listen(elem, DOM_EVENTS.CLICK, cb);
    }

    function isSmallCardElem(elem) {
        var classList = elem.classList;
        return classList &&
                classList.contains(CARD_CLASS_NAME) &&
                !classList.contains(BIG_CARD_CLASS_NAME);
    }

    function getCardElem(elem) {
        var output;

        if (isSmallCardElem(elem)) {
            output = elem;
        } else if (elem.parentNode) {
            output = getCardElem(elem.parentNode);
        } else {
            output = null;
        }

        return output;
    }

    /*jslint eqeq: true*/
    function truthy(elem) {
        return elem != null;
    }
    /*jslint eqeq: false*/

    function hideDisplayedCard() {
        body.classList.remove(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function setData(element) {
        function setElementData(name, value) {
            if (element.dataset) {
                element.dataset[name] = value;
            } else {
                element.setAttribute('data-' + name, value);
            }
        }

        return function (data) {
            setElementData.apply(element, data);
        };
    }

    function getData(element, name) {
        var output;
        if (element.dataset) {
            output = element.dataset[name];
        } else {
            output = element.getAttribute('data-' + name);
        }

        return output;
    }

    function setAttributes(element) {
        return function (attrib) {
            element.setAttribute.apply(element, attrib);
        };
    }

    function fibonacci(test, acc) {
        var val;

        if (acc.length < 2) {
            val = 1;
        } else {
            val = acc[acc.length - 2] + acc[acc.length - 1];
        }

        if (test(val)) {
            acc.push(val);

            return fibonacci(test, acc);
        }

        return acc;
    }

    function processDisplayedValue(value) {
        if (+value === 0.5) {
            value = '1/2';
        } else if (value === 'coffe') {
            value = '';
        } else if (+value === Infinity) {
            value = '∞';
        }
        return String(value);
    }

    function createElement(name, classes, data, attributes, text) {
        var element = document.createElement(name);

        classes.forEach(function (cn) {
            element.classList.add(cn);
        });
        data.forEach(setData(element));
        attributes.forEach(setAttributes(element));

        if (truthy(text)) {
            element.innerHTML = text;
        }

        return element;
    }

    function createDiv(classes, data, attributes, text) {
        return createElement('div', classes, data, attributes, text);
    }

    function createCardSide(element, which, text) {
        var cardSide = createDiv([CARD_SIDE_CLASS_NAME, which], [], [], text);
        element.appendChild(cardSide);
    }

    function createCard(value) {
        var card = createDiv([CARD_CLASS_NAME, SMALL_CARD_CLASS_NAME], [['value', value]], []);

        createCardSide(card, FRONT_CARD_CLASS_NAME, processDisplayedValue(value));
        createCardSide(card, BACK_CARD_CLASS_NAME);

        return card;
    }

    function showDisplayedCard(value) {
        var card = byId('DisplayedCard');

        hideDisplayedCard();

        setTimeout(function () {
            body.classList.add(SHOW_CARD_IN_BIG_CLASS_NAME);
            card.querySelector('.' + FRONT_CARD_CLASS_NAME).innerHTML = processDisplayedValue(value);
        }, 200);
    }

    function toArray(args) {
        return Array.prototype.slice.call(args);
    }

    function removeCard(card) {
        place.removeChild(card);
    }

    function removeCards() {
        var cards = toArray(place.querySelectorAll('.' + CARD_CLASS_NAME + ':not(.' + BIG_CARD_CLASS_NAME + ')'));

        cards.forEach(removeCard);
    }

    function addCards(cards) {
        var fragment = document.createDocumentFragment();

        cards.forEach(function (val) {
            fragment.appendChild(createCard(val));
        });

        place.appendChild(fragment);
    }

    function showClickedCard(cardElem) {
        var value;

        if (cardElem) {
            value = getData(cardElem, 'value');
            showDisplayedCard(value);
        }
    }

    function cardChangeDisabled() {
        return showing || !placeClickEnabled;
    }

    function isBigCardVisible() {
        return body.classList.contains(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function hideBigCard() {
        body.classList.remove(SHOW_CARD_IN_BIG_CLASS_NAME);
    }

    function onPlaceClick(event) {
        var cardElem;

        event.preventDefault();
        event.stopPropagation();

        if (cardChangeDisabled()) {
            return;
        }

        if (isBigCardVisible()) {
            hideBigCard();
        } else {
            cardElem = getCardElem(event.target);

            if (cardElem) {
                showClickedCard(cardElem);
            }
        }

        showing = true;

        setTimeout(function () {
            showing = false;
        }, 200);
    }

    function disablePlaceClick() {
        placeClickEnabled = false;
    }

    function enablePlaceClick() {
        placeClickEnabled = true;
    }

    function getFibonacciCards() {
        return fibonacci(function (last) {
            return last < 100; // generate fibonacci until last item is less then 100
        }, [0]).reduce(function (prev, current, index, array) {
            var arr = prev || [prev];

            if (arr.indexOf(current) === -1) {
                return arr.concat(current);
            }

            return arr;
        }, ['?', 0.5]);
    }

    function getStandardCards() {
        return ['coffe', '?', 0, 0.5, 1, 2, 3, 5, 8, 13, 20, 40, 100, Infinity];
    }

    function getTshirtCards() {
        return ['XS', 'S', 'M', 'L', 'XL', 'XL', '?'];
    }

    function setActiveCardTypeButton(type) {
        var toolbar = byId('Toolbar');
        if (type === 'standard') {
            toolbar.classList.add('active-standard');
        } else {
            toolbar.classList.remove('active-standard');
        }

        if (type === 'tshirt') {
            toolbar.classList.add('active-tshirt');
        } else {
            toolbar.classList.remove('active-tshirt');
        }

        if (type === 'fibonacci') {
            toolbar.classList.add('active-fibonacci');
        } else {
            toolbar.classList.remove('active-fibonacci');
        }
    }

    function getCards(type) {
        var cards;

        if (type === 'fibonacci') {
            cards = getFibonacciCards();
        } else if (type === 'tshirt') {
            cards = getTshirtCards();
        } else {
            cards = getStandardCards();
        }

        return cards;
    }

    function getSelectCardCb(type) {
        return function () {
            if (cardChangeDisabled()) {
                return;
            }
            removeCards();
            addCards(getCards(type));
            setActiveCardTypeButton(type);
        };
    }

    listen(window, 'load', function () {
        place = byId('PokerPlace');
        body = document.getElementsByTagName('body')[0];

        removeCards();
        addCards(getStandardCards());

        onClick(body, onPlaceClick);
        listen(place, enablePlaceClick);
        listen(body, 'touchstart', enablePlaceClick);
        listen(body, 'touchmove', disablePlaceClick);
        listen(body, DOM_EVENTS.TOUCHEND, onPlaceClick);

        onClick('CardTypeSelectStandard', getSelectCardCb('standard'));
        onClick('CardTypeSelectTshirt', getSelectCardCb('tshirt'));
        onClick('CardTypeSelectFibonacci', getSelectCardCb('fibonacci'));
        listen(byId('CardTypeSelectStandard'), DOM_EVENTS.TOUCHEND, getSelectCardCb('standard'));
        listen(byId('CardTypeSelectTshirt'), DOM_EVENTS.TOUCHEND, getSelectCardCb('tshirt'));
        listen(byId('CardTypeSelectFibonacci'), DOM_EVENTS.TOUCHEND, getSelectCardCb('fibonacci'));

        onClick('DisplayedCard', hideDisplayedCard);
    }, false);
}());
<|endoftext|>


<commit_before>function trace(s)
{
	console.debug(s);
}

function urlencode(str)	//function borrowed from http://www.albionresearch.com/misc/urlencode.php
{
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < str.length; i++ ) {
		var ch = str.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '"
                        + ch
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	}

	return encoded;
};

//Toggles element with name "n" between visible and hidden
function toggle_element_by_name(n)
{
	var e = document.getElementById(n);
	e.style.display = (e.style.display?'':'none');
}

//Makes element with name "n" invisible in browser
function hide_element_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.display = 'none';
}

//Makes element with name "n" visible in browser
function show_element_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.display = '';
}

function set_visible_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.visibility="visible";
}

function set_invisible_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.visibility="hidden";
}

function add_div(e, idname, style)
{
	var c=document.createElement('div');

	c.setAttribute('id', idname);
	c.className = style;
	e.appendChild(c);

	return c;
}

function add_span(e)
{
	var c=document.createElement('span');

//	c.setAttribute('id', idname);
//	c.className = style;
	e.appendChild(c);

	return c;
}
function empty_element_by_name(n)
{
	var e=document.getElementById(n);

	while (e.hasChildNodes())
		e.removeChild(e.firstChild);
}

function fill_element_by_name(n,txt)
{
	var e = document.getElementById(n);
	empty_element(e);

	e.innerHTML = txt;
}

function empty_element(e)
{
	while (e.hasChildNodes()) e.removeChild(e.firstChild);
}

//checks if image n has been loaded, waits until it is done otherwise
function image_loaded(n)
{
	var e = document.getElementById(n);

	trace('image_loaded('+n+') w:'+e.width+',h:'+e.height);

	//IE. fixme:untested
	if (!e.complete) {
		return false;
	}

	//Firefox
	if (typeof e.naturalWidth != "undefined" && e.naturalWidth == 0) {
		return false;
	}

	return true;
}

//resizes current window to the same size as image n
function resize_wnd_to_img(n)
{
	var e = document.getElementById(n);
	trace('resize_wnd_to_img('+n+') w:'+e.width+',h:'+e.height);
	var NS = (navigator.appName=="Netscape")?true:false;

	iWidth = (NS)?window.innerWidth:document.body.clientWidth;
	iHeight = (NS)?window.innerHeight:document.body.clientHeight;
	iWidth = e.width - iWidth;
	iHeight = e.height - iHeight;
	window.resizeBy(iWidth, iHeight);
	self.focus();
}

function pause(ms)
{
	var now = new Date();
	var exitTime = now.getTime() + ms;

	while(true) {
		now = new Date();
		if(now.getTime() > exitTime) return;
	}
}

/* sends a ajax poll submit */
function submit_poll(id,opt)
{
	//alert('fixme: submit_poll() add ajax submit. id ' + id + ', opt ' + opt);
	ajax_poll(id,opt);

	hide_element_by_name('poll'+id);
	show_element_by_name('poll_voted'+id);
}

function get_poll_csv(id)
{
	var w = window.open(_ext_core+'csv_poll.php?id='+id+_ext_ref, '_blank');
	w.focus();
}

//Loads image id into holder-div
function loadImage(id, holder)
{
	var e = document.getElementById(holder);
	empty_element(e);

	var i = document.createElement('img');
	i.setAttribute('src', _ext_core+'file.php?id='+id+_ext_ref);
	e.appendChild(i);

	var j = document.getElementById('image_comments_iframe');
	j.setAttribute('src', _ext_core+'html_imgcomments.php?i='+id+_ext_ref);
}

function scroll_up(e, step, offs)
{
	e.scrollTop -= step;
	offs += step;

	if (offs<0) setTimeout(function() {scroll_up(e,step,offs)}, 1);
}

function scroll_down(e, step, offs)
{
	e.scrollTop += step;
	offs -= step;

	if (offs>0) setTimeout(function() {scroll_down(e,step,offs)}, 1);
}

//scroll the content of element name "n" by offset pixels. use negative value of offset to scroll up, positive to scroll down
function scroll_element_content(n,offs)
{
	var e = document.getElementById(n);

	if (offs>0) {
		setTimeout(function() {scroll_down(e,6,offs)}, 1);
	} else {
		setTimeout(function() {scroll_up(e,6,offs)}, 1);
	}
}

//expands size of <input type="text" id="n">
function expand_input(e)
{
	var x=document.getElementById(e);
	if (x.size < 120) x.size += 20;
	//fixme: set focus to start of inputted text after resizing
}

function urlOpen(u)
{
	document.location = u;
}

function in_arr(arr,val)
{
	for (var i=0; i<arr.length; i++) {
		if (arr[i] == val) return true;
	}
	return false;
}

function arr_del(arr,val)
{
	for (var i=0; i<arr.length; i++) {
		if (arr[i] == val) delete arr[i];	//fixme: this will leave arr[i] undefined, arr.length will not be changed
	}
}

function set_class(e,c){
	var x=document.getElementById(e);
	x.className=c;
}

function add_node(e,t,s) {
	var c=document.createElement('div');
	e.appendChild(c);
	var tx=document.createTextNode(t);
	c.appendChild(tx);
	c.className=s;
	return c;
}

function add_node_and_focus(e,t,s) {
	var c=add_node(e,t,s);
	c.scrollIntoView(false);
}

/* focuses on the faq item #i */
function faq_focus(n) {
	e = document.getElementById('faq_'+n);
	if (!e) return;
	e.style.display = '';	//show

	for (i=0;i<=100;i++) {
		if (i==n) continue;
		e = document.getElementById('faq_'+i);
		if (!e) return;
		e.style.display = 'none';	//hide

		hide_element_by_name('faq_edit_'+i);
		show_element_by_name('faq_holder_'+i);
	}
}

//used with $files->showThumbnails(). displays comments div and shrinks currently displayed image
//n=image id currently displayed
var comments_shown = false;
var org_w, org_h;
function show_image_comments(n)
{
	e = document.getElementById('img_'+n);

	if (!comments_shown) {
		show_element_by_name('image_comments_content');
		comments_shown = true;
		org_w = e.width;
		org_h = e.height;
		//fixme: shrinking image here dont work properly, first time it resizes it gets wrong then it gets correct
		//e.width *= 0.5;
		//e.height *= 0.5;
		return;
	}

	hide_element_by_name('image_comments_content');
	comments_shown = false;
	e.width = org_w;
	e.height = org_h;
}

//shows fileId i in a new window, displayed as a image
function popup_imgview(i,w,h)
{
	if(!w)w=300;
	if(!h)h=200;
	p = window.open(_ext_core+'popup_imgview.php?id='+i+_ext_ref, 'name', 'width='+w+',height='+h);
	if (window.focus) p.focus();
}

//sets element name "n" to the html content of "txt"
function set_div_content(n, txt)
{
	var e = document.getElementById(n);
	empty_element(e);

	e.innerHTML = txt;
	show_element_by_name(n);
}

/**
 * Format selection
 *
 * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
 * of selection if there is none. Copied and adapted from phpBB
 *
 * @author phpBB development team
 * @author MediaWiki development team
 * @author Andreas Gohr <andi@splitbrain.org>
 * @author Jim Raynor <jim_raynor@web.de>
 */
function insertTags(edid,tagOpen, tagClose, sampleText) {
  var txtarea = document.getElementById(edid);
  // IE
  if(document.selection  && !is_gecko) {
    var theSelection = document.selection.createRange().text;
    var replaced = true;
    if(!theSelection){
      replaced = false;
      theSelection=sampleText;
    }
    txtarea.focus();

    // This has change
    var text = theSelection;
    if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
      theSelection = theSelection.substring(0, theSelection.length - 1);
      r = document.selection.createRange();
      r.text = tagOpen + theSelection + tagClose + " ";
    } else {
      r = document.selection.createRange();
      r.text = tagOpen + theSelection + tagClose;
    }
    if(!replaced){
      r.moveStart('character',-text.length-tagClose.length);
      r.moveEnd('character',-tagClose.length);
    }
    r.select();
  // Mozilla
  } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
    replaced = false;
    var startPos = txtarea.selectionStart;
    var endPos   = txtarea.selectionEnd;
    if(endPos - startPos){ replaced = true; }
    var scrollTop=txtarea.scrollTop;
    var myText = (txtarea.value).substring(startPos, endPos);
    if(!myText) { myText=sampleText;}
    if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
      subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
    } else {
      subst = tagOpen + myText + tagClose;
    }
    txtarea.value = txtarea.value.substring(0, startPos) + subst +
                    txtarea.value.substring(endPos, txtarea.value.length);
    txtarea.focus();

    //set new selection
    if(replaced){
      var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
      txtarea.selectionStart=cPos;
      txtarea.selectionEnd=cPos;
    }else{
      txtarea.selectionStart=startPos+tagOpen.length;
      txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
    }
    txtarea.scrollTop=scrollTop;
  // All others
  } else {
    var copy_alertText=alertText;
    var re1=new RegExp("\\$1","g");
    var re2=new RegExp("\\$2","g");
    copy_alertText=copy_alertText.replace(re1,sampleText);
    copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);

    if (sampleText) {
      text=prompt(copy_alertText);
    } else {
      text="";
    }
    if(!text) { text=sampleText;}
    text=tagOpen+text+tagClose;
    //append to the end
    txtarea.value += "\n"+text;

    // in Safari this causes scrolling
    if(!is_safari) {
      txtarea.focus();
    }

  }
  // reposition cursor if possible
  if (txtarea.createTextRange){
    txtarea.caretPos = document.selection.createRange().duplicate();
  }
}
<commit_msg>Lite förklaringar<commit_after>function trace(s)
{
	console.debug(s);
}

function urlencode(str)	//function borrowed from http://www.albionresearch.com/misc/urlencode.php
{
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < str.length; i++ ) {
		var ch = str.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '"
                        + ch
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	}

	return encoded;
};

//Toggles element with name "n" between visible and hidden
//
//If this function makes an element "hidden" the browser
//regards it as non-existent and does not regard it as being
//part of the page-layout
function toggle_element_by_name(n)
{
	var e = document.getElementById(n);
	e.style.display = (e.style.display?'':'none');
}

//Makes element with name "n" invisible in browser
function hide_element_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.display = 'none';
}

//Makes element with name "n" visible in browser
function show_element_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.display = '';
}

//This function, as opposed to the ones above, has the
//browser render the content but show / dont show it
function set_visible_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.visibility="visible";
}

function set_invisible_by_name(n)
{
	var e = document.getElementById(n);
	if (!e) {
		//alert('fixme: element ' + n + ' not found');
		return;
	}
	e.style.visibility="hidden";
}

function add_div(e, idname, style)
{
	var c=document.createElement('div');

	c.setAttribute('id', idname);
	c.className = style;
	e.appendChild(c);

	return c;
}

function add_span(e)
{
	var c=document.createElement('span');

//	c.setAttribute('id', idname);
//	c.className = style;
	e.appendChild(c);

	return c;
}
function empty_element_by_name(n)
{
	var e=document.getElementById(n);

	while (e.hasChildNodes())
		e.removeChild(e.firstChild);
}

function fill_element_by_name(n,txt)
{
	var e = document.getElementById(n);
	empty_element(e);

	e.innerHTML = txt;
}

function empty_element(e)
{
	while (e.hasChildNodes()) e.removeChild(e.firstChild);
}

//checks if image n has been loaded, waits until it is done otherwise
function image_loaded(n)
{
	var e = document.getElementById(n);

	trace('image_loaded('+n+') w:'+e.width+',h:'+e.height);

	//IE. fixme:untested
	if (!e.complete) {
		return false;
	}

	//Firefox
	if (typeof e.naturalWidth != "undefined" && e.naturalWidth == 0) {
		return false;
	}

	return true;
}

//resizes current window to the same size as image n
function resize_wnd_to_img(n)
{
	var e = document.getElementById(n);
	trace('resize_wnd_to_img('+n+') w:'+e.width+',h:'+e.height);
	var NS = (navigator.appName=="Netscape")?true:false;

	iWidth = (NS)?window.innerWidth:document.body.clientWidth;
	iHeight = (NS)?window.innerHeight:document.body.clientHeight;
	iWidth = e.width - iWidth;
	iHeight = e.height - iHeight;
	window.resizeBy(iWidth, iHeight);
	self.focus();
}

function pause(ms)
{
	var now = new Date();
	var exitTime = now.getTime() + ms;

	while(true) {
		now = new Date();
		if(now.getTime() > exitTime) return;
	}
}

/* sends a ajax poll submit */
function submit_poll(id,opt)
{
	//alert('fixme: submit_poll() add ajax submit. id ' + id + ', opt ' + opt);
	ajax_poll(id,opt);

	hide_element_by_name('poll'+id);
	show_element_by_name('poll_voted'+id);
}

function get_poll_csv(id)
{
	var w = window.open(_ext_core+'csv_poll.php?id='+id+_ext_ref, '_blank');
	w.focus();
}

//Loads image id into holder-div
function loadImage(id, holder)
{
	var e = document.getElementById(holder);
	empty_element(e);

	var i = document.createElement('img');
	i.setAttribute('src', _ext_core+'file.php?id='+id+_ext_ref);
	e.appendChild(i);

	var j = document.getElementById('image_comments_iframe');
	j.setAttribute('src', _ext_core+'html_imgcomments.php?i='+id+_ext_ref);
}

function scroll_up(e, step, offs)
{
	e.scrollTop -= step;
	offs += step;

	if (offs<0) setTimeout(function() {scroll_up(e,step,offs)}, 1);
}

function scroll_down(e, step, offs)
{
	e.scrollTop += step;
	offs -= step;

	if (offs>0) setTimeout(function() {scroll_down(e,step,offs)}, 1);
}

//scroll the content of element name "n" by offset pixels. use negative value of offset to scroll up, positive to scroll down
function scroll_element_content(n,offs)
{
	var e = document.getElementById(n);

	if (offs>0) {
		setTimeout(function() {scroll_down(e,6,offs)}, 1);
	} else {
		setTimeout(function() {scroll_up(e,6,offs)}, 1);
	}
}

//expands size of <input type="text" id="n">
function expand_input(e)
{
	var x=document.getElementById(e);
	if (x.size < 120) x.size += 20;
	//fixme: set focus to start of inputted text after resizing
}

function urlOpen(u)
{
	document.location = u;
}

function in_arr(arr,val)
{
	for (var i=0; i<arr.length; i++) {
		if (arr[i] == val) return true;
	}
	return false;
}

function arr_del(arr,val)
{
	for (var i=0; i<arr.length; i++) {
		if (arr[i] == val) delete arr[i];	//fixme: this will leave arr[i] undefined, arr.length will not be changed
	}
}

function set_class(e,c){
	var x=document.getElementById(e);
	x.className=c;
}

function add_node(e,t,s) {
	var c=document.createElement('div');
	e.appendChild(c);
	var tx=document.createTextNode(t);
	c.appendChild(tx);
	c.className=s;
	return c;
}

function add_node_and_focus(e,t,s) {
	var c=add_node(e,t,s);
	c.scrollIntoView(false);
}

/* focuses on the faq item #i */
function faq_focus(n) {
	e = document.getElementById('faq_'+n);
	if (!e) return;
	e.style.display = '';	//show

	for (i=0;i<=100;i++) {
		if (i==n) continue;
		e = document.getElementById('faq_'+i);
		if (!e) return;
		e.style.display = 'none';	//hide

		hide_element_by_name('faq_edit_'+i);
		show_element_by_name('faq_holder_'+i);
	}
}

//used with $files->showThumbnails(). displays comments div and shrinks currently displayed image
//n=image id currently displayed
var comments_shown = false;
var org_w, org_h;
function show_image_comments(n)
{
	e = document.getElementById('img_'+n);

	if (!comments_shown) {
		show_element_by_name('image_comments_content');
		comments_shown = true;
		org_w = e.width;
		org_h = e.height;
		//fixme: shrinking image here dont work properly, first time it resizes it gets wrong then it gets correct
		//e.width *= 0.5;
		//e.height *= 0.5;
		return;
	}

	hide_element_by_name('image_comments_content');
	comments_shown = false;
	e.width = org_w;
	e.height = org_h;
}

//shows fileId i in a new window, displayed as a image
function popup_imgview(i,w,h)
{
	if(!w)w=300;
	if(!h)h=200;
	p = window.open(_ext_core+'popup_imgview.php?id='+i+_ext_ref, 'name', 'width='+w+',height='+h);
	if (window.focus) p.focus();
}

//sets element name "n" to the html content of "txt"
function set_div_content(n, txt)
{
	var e = document.getElementById(n);
	empty_element(e);

	e.innerHTML = txt;
	show_element_by_name(n);
}

/**
 * Format selection
 *
 * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
 * of selection if there is none. Copied and adapted from phpBB
 *
 * @author phpBB development team
 * @author MediaWiki development team
 * @author Andreas Gohr <andi@splitbrain.org>
 * @author Jim Raynor <jim_raynor@web.de>
 */
function insertTags(edid,tagOpen, tagClose, sampleText) {
  var txtarea = document.getElementById(edid);
  // IE
  if(document.selection  && !is_gecko) {
    var theSelection = document.selection.createRange().text;
    var replaced = true;
    if(!theSelection){
      replaced = false;
      theSelection=sampleText;
    }
    txtarea.focus();

    // This has change
    var text = theSelection;
    if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
      theSelection = theSelection.substring(0, theSelection.length - 1);
      r = document.selection.createRange();
      r.text = tagOpen + theSelection + tagClose + " ";
    } else {
      r = document.selection.createRange();
      r.text = tagOpen + theSelection + tagClose;
    }
    if(!replaced){
      r.moveStart('character',-text.length-tagClose.length);
      r.moveEnd('character',-tagClose.length);
    }
    r.select();
  // Mozilla
  } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
    replaced = false;
    var startPos = txtarea.selectionStart;
    var endPos   = txtarea.selectionEnd;
    if(endPos - startPos){ replaced = true; }
    var scrollTop=txtarea.scrollTop;
    var myText = (txtarea.value).substring(startPos, endPos);
    if(!myText) { myText=sampleText;}
    if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
      subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
    } else {
      subst = tagOpen + myText + tagClose;
    }
    txtarea.value = txtarea.value.substring(0, startPos) + subst +
                    txtarea.value.substring(endPos, txtarea.value.length);
    txtarea.focus();

    //set new selection
    if(replaced){
      var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
      txtarea.selectionStart=cPos;
      txtarea.selectionEnd=cPos;
    }else{
      txtarea.selectionStart=startPos+tagOpen.length;
      txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
    }
    txtarea.scrollTop=scrollTop;
  // All others
  } else {
    var copy_alertText=alertText;
    var re1=new RegExp("\\$1","g");
    var re2=new RegExp("\\$2","g");
    copy_alertText=copy_alertText.replace(re1,sampleText);
    copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);

    if (sampleText) {
      text=prompt(copy_alertText);
    } else {
      text="";
    }
    if(!text) { text=sampleText;}
    text=tagOpen+text+tagClose;
    //append to the end
    txtarea.value += "\n"+text;

    // in Safari this causes scrolling
    if(!is_safari) {
      txtarea.focus();
    }

  }
  // reposition cursor if possible
  if (txtarea.createTextRange){
    txtarea.caretPos = document.selection.createRange().duplicate();
  }
}
<|endoftext|>


<commit_before>var express = require('express');
var app = express();

// handlebars
var handlebars = require('express-handlebars').create({
	defaultLayout:'main',
	extname:'.hbs'
});
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');

// mongoose
var mongoose = require('mongoose');
var opts = {
	server: {
		socketOptions: { keepAlive: 1 }
	}
};

// custom modules
var credentials = require('./credentials.js');
var riot = require('./lib/riot/riot.js')({
	type: "match",
	key: credentials.riot.key,
	region: 'NA'
});

riot.test(1907069332);

mongoose.connect(credentials.mongo.connectionString, opts);

// Set port and ip
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 8080);
app.set('ip', process.env.OPENSHIFT_NODEJS_IP);

// Set up middle ware for client side assets
app.use(express.static(__dirname + '/public'));

// Set up routes
require('./routes.js')(app);

app.listen(app.get('port'), app.get('ip'), function() {
	console.log("Server is running");
});<commit_msg>request htmls are case sensitive? huh<commit_after>var express = require('express');
var app = express();

// handlebars
var handlebars = require('express-handlebars').create({
	defaultLayout:'main',
	extname:'.hbs'
});
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');

// mongoose
var mongoose = require('mongoose');
var opts = {
	server: {
		socketOptions: { keepAlive: 1 }
	}
};

// custom modules
var credentials = require('./credentials.js');
var riot = require('./lib/riot/riot.js')({
	type: "match",
	key: credentials.riot.key,
	region: 'na'
});

riot.test(1907069332);

mongoose.connect(credentials.mongo.connectionString, opts);

// Set port and ip
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 8080);
app.set('ip', process.env.OPENSHIFT_NODEJS_IP);

// Set up middle ware for client side assets
app.use(express.static(__dirname + '/public'));

// Set up routes
require('./routes.js')(app);

app.listen(app.get('port'), app.get('ip'), function() {
	console.log("Server is running");
});<|endoftext|>


<commit_before>(function() {
    'use strict';

    // Variables with names starting with '$' are DOM-elements.
    // Function and variables with names starting with 'g' are global.
    // Variables with names starting with 'a' are parameters.

    // Canvas related.
    var $buttonsContainer = document.getElementById('buttons_container'),
        $canvasContainer = document.getElementById('canvas_container'),
        $canvas = document.getElementById('canvas'),
        gCtx = $canvas.getContext('2d'),
        gCanvasMetrics = {
            DEFAULT_WIDTH: 640,
            DEFAULT_HEIGHT: 480,
            width: null,
            height: null,
            scaleFactor: null,
            offsetX: null,
            offsetY: null,
        };

    // Images related.
    var gImagesPaths = ['img/card1.png', 'img/card2.png', 'img/card3.png'],
        gImagesMetrics = {
            DEFAULT_WIDTH: 150,
            DEFAULT_HEIGHT: 250,
            OFFSET_X: 10,
            OFFSET_Y: 20,
            ADDITION: 20
        },
        gImages = {},
        gImagesOnCanvasStack = [];

    // Dragging related.
    var gCurrentDraggingImageIndex = -1,
        gLastCoords = { x: null, y: null },
        gIsAnimationFrameRequested = false,
        gMouseEvent = null;

    // Buttons related.
    var gButtons = [];

    // Main code.

    gInitCanvasAndButtonsResizing();
    gStartImagesLoading();

    $canvas.onmousedown = function(aMouseEvent) {
        var currentCoords = gCalculateCanvasCoordsFromMouseEvent(aMouseEvent);
        gCurrentDraggingImageIndex = gGetIndexOfImageUnderMouse(currentCoords.x, currentCoords.y);
        if (~gCurrentDraggingImageIndex) {
            $canvasContainer.classList.add('dragging');
            gLastCoords.x = currentCoords.x;
            gLastCoords.y = currentCoords.y;
        }
    };

    $canvas.onmousemove = function(aMouseEvent) {
        if (~gCurrentDraggingImageIndex && !gIsAnimationFrameRequested) {
            gIsAnimationFrameRequested = true;
            gMouseEvent = aMouseEvent;
            window.requestAnimationFrame(gMoveDraggingImageAndRedraw.bind(null, gCurrentDraggingImageIndex));
        }
    };

    $canvas.onmouseup = function(aMouseEvent) {
        gCurrentDraggingImageIndex = -1;

        $canvasContainer.classList.remove('dragging');

        gMouseEvent = null;
    };

    // Functions.

    function gInitCanvasAndButtonsResizing() {
        var debounceTmt = null;

        //initial canvas size setting
        setCanvasSize();

        window.onresize = function() {
            clearTimeout(debounceTmt);
            debounceTmt = setTimeout(function() {
                setCanvasSize();
                setButtonsPosition();
                gDraw();
            }, 100);
        };

        function setCanvasSize() {
            gCanvasMetrics.width = window.innerWidth;
            gCanvasMetrics.height = window.innerHeight;

            $canvas.width = gCanvasMetrics.width;
            $canvas.height = gCanvasMetrics.height;
            console.log('Canvas size is set to ' + gCanvasMetrics.width + 'x' + gCanvasMetrics.height);

            gCanvasMetrics.scaleFactor = Math.min(gCanvasMetrics.width/gCanvasMetrics.DEFAULT_WIDTH,
                                                 gCanvasMetrics.height/gCanvasMetrics.DEFAULT_HEIGHT);
            console.log('Scale factor is set to ' + gCanvasMetrics.scaleFactor);

            gCanvasMetrics.offsetX = Math.floor((gCanvasMetrics.width - gCanvasMetrics.DEFAULT_WIDTH*gCanvasMetrics.scaleFactor)/2);
            gCanvasMetrics.offsetY = Math.floor((gCanvasMetrics.height - gCanvasMetrics.DEFAULT_HEIGHT*gCanvasMetrics.scaleFactor)/2);
            console.log('Offsets: x=' + gCanvasMetrics.offsetX + ', y=' + gCanvasMetrics.offsetY);

            gCtx.setTransform(gCanvasMetrics.scaleFactor, 0, 0, gCanvasMetrics.scaleFactor, gCanvasMetrics.offsetX, gCanvasMetrics.offsetY);
        }

        function setButtonsPosition() {
            for (var i = 0, len = gButtons.length; i < len; i++) {
                gSetButtonPosition(gButtons[i]);
            }
        }
    }

    function gSetButtonPosition(aButton) {
        var xFactor = gImagesPaths.length > 1 ? 0.1 + 0.8*aButton.number/(gImagesPaths.length - 1) : 0.5;
        aButton.style.top = gCanvasMetrics.height*0.8 + 'px';
        aButton.style.left = (gCanvasMetrics.offsetX + gCanvasMetrics.scaleFactor*gCanvasMetrics.DEFAULT_WIDTH*xFactor) + 'px';
    }

    function gStartImagesLoading() {
        for (var i = 0, len = gImagesPaths.length; i < len; i++) {
            gImages[i] = new Image();
            gImages[i].onload = addButtonForImage.bind(null, i);
            gImages[i].src = gImagesPaths[i];
        }

        function addButtonForImage(aNumber) {
            console.log('Image ' + aNumber + ' is loaded.');

            var $button = document.createElement('button');
            $button.className = 'image_button';
            $button.textContent = 'Image ' + (aNumber + 1);
            $button.number = aNumber;
            gSetButtonPosition($button);
            $buttonsContainer.insertBefore($button, null);
            $button.onclick = buttonClickAction.bind(null, aNumber);

            gButtons.push($button);
        }

        function buttonClickAction(aNumber) {
            var lastImageOnStack, index = getIndexOfImageOnStack(aNumber);

            if (~index) {
                gClearAreaOfImageWithIndex(index);
                // Remove image from canvas image stack array.
                gImagesOnCanvasStack = gImagesOnCanvasStack.slice(0, index).concat(gImagesOnCanvasStack.slice(index + 1));
            } else {
                lastImageOnStack = gImagesOnCanvasStack.length ? gImagesOnCanvasStack[gImagesOnCanvasStack.length - 1] : null;
                gImagesOnCanvasStack.push({
                    x: lastImageOnStack ? lastImageOnStack.x + gImagesMetrics.OFFSET_X : (gCanvasMetrics.DEFAULT_WIDTH - gImagesMetrics.DEFAULT_WIDTH)/2,
                    y: lastImageOnStack ? lastImageOnStack.y + gImagesMetrics.OFFSET_Y : (gCanvasMetrics.DEFAULT_HEIGHT - gImagesMetrics.DEFAULT_HEIGHT)/2,
                    imageNo: aNumber
                });
            }
            gDraw();
        }

        function getIndexOfImageOnStack(aNumber) {
            for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
                if (gImagesOnCanvasStack[i].imageNo === aNumber) {
                    return i;
                }
            }
            return -1;
        }
    }

    function gDraw() {
        var currentImage;
        for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
            currentImage = gImagesOnCanvasStack[i];
            gCtx.drawImage(gImages[currentImage.imageNo], currentImage.x, currentImage.y);
        }
    }

    function gCalculateCanvasCoordsFromMouseEvent(aMouseEvent) {
        var x = (aMouseEvent.clientX - gCanvasMetrics.offsetX)/gCanvasMetrics.scaleFactor,
            y = (aMouseEvent.clientY - gCanvasMetrics.offsetY)/gCanvasMetrics.scaleFactor;
        return { x: x, y: y };
    }

    function gGetIndexOfImageUnderMouse(aX, aY) {
        var currentImage;
        for (var i = gImagesOnCanvasStack.length - 1; i >= 0; i--) {
            currentImage = gImagesOnCanvasStack[i];
            if (aX >= currentImage.x && aX <= currentImage.x + gImagesMetrics.DEFAULT_WIDTH &&
                aY >= currentImage.y && aY <= currentImage.y + gImagesMetrics.DEFAULT_HEIGHT) {
                return i;
            }
        }
        return -1;
    }

    function gClearAreaOfImageWithIndex(aIndex) {
        var image = gImagesOnCanvasStack[aIndex];
        gCtx.clearRect(
            image.x - gImagesMetrics.ADDITION,
            image.y - gImagesMetrics.ADDITION,
            gImagesMetrics.DEFAULT_WIDTH + 2*gImagesMetrics.ADDITION,
            gImagesMetrics.DEFAULT_HEIGHT + 2*gImagesMetrics.ADDITION
        );
    }

    function gMoveDraggingImageAndRedraw(aIndex) {
        gIsAnimationFrameRequested = false;

        var currentCoords = gCalculateCanvasCoordsFromMouseEvent(gMouseEvent);

        gClearAreaOfImageWithIndex(aIndex);

        gImagesOnCanvasStack[aIndex].x += currentCoords.x - gLastCoords.x;
        gImagesOnCanvasStack[aIndex].y += currentCoords.y - gLastCoords.y;

        gLastCoords.x = currentCoords.x;
        gLastCoords.y = currentCoords.y;

        gDraw();
    }
})();<commit_msg>Make onMouseMove action be called only on dragging<commit_after>(function() {
    'use strict';

    // Variables with names starting with '$' are DOM-elements.
    // Function and variables with names starting with 'g' are global.
    // Variables with names starting with 'a' are parameters.

    // Canvas related.
    var $buttonsContainer = document.getElementById('buttons_container'),
        $canvasContainer = document.getElementById('canvas_container'),
        $canvas = document.getElementById('canvas'),
        gCtx = $canvas.getContext('2d'),
        gCanvasMetrics = {
            DEFAULT_WIDTH: 640,
            DEFAULT_HEIGHT: 480,
            width: null,
            height: null,
            scaleFactor: null,
            offsetX: null,
            offsetY: null,
        };

    // Images related.
    var gImagesPaths = ['img/card1.png', 'img/card2.png', 'img/card3.png'],
        gImagesMetrics = {
            DEFAULT_WIDTH: 150,
            DEFAULT_HEIGHT: 250,
            OFFSET_X: 10,
            OFFSET_Y: 20,
            ADDITION: 20
        },
        gImages = {},
        gImagesOnCanvasStack = [];

    // Dragging related.
    var gCurrentDraggingImageIndex = -1,
        gLastCoords = { x: null, y: null },
        gIsAnimationFrameRequested = false,
        gMouseEvent = null;

    // Buttons related.
    var gButtons = [];

    // Main code.

    gInitCanvasAndButtonsResizing();
    gStartImagesLoading();

    $canvas.onmousedown = function(aMouseEvent) {
        var currentCoords = gCalculateCanvasCoordsFromMouseEvent(aMouseEvent);
        gCurrentDraggingImageIndex = gGetIndexOfImageUnderMouse(currentCoords.x, currentCoords.y);
        if (~gCurrentDraggingImageIndex) {
            $canvasContainer.classList.add('dragging');

            gLastCoords.x = currentCoords.x;
            gLastCoords.y = currentCoords.y;

            $canvas.onmousemove = gCanvasOnMouseMoveAction;
        }
    };

    $canvas.onmouseup = function(aMouseEvent) {
        gCurrentDraggingImageIndex = -1;

        $canvasContainer.classList.remove('dragging');

        gMouseEvent = null;

        $canvas.onmousemove = null;
    };

    // Functions.

    function gInitCanvasAndButtonsResizing() {
        var debounceTmt = null;

        //initial canvas size setting
        setCanvasSize();

        window.onresize = function() {
            clearTimeout(debounceTmt);
            debounceTmt = setTimeout(function() {
                setCanvasSize();
                setButtonsPosition();
                gDraw();
            }, 100);
        };

        function setCanvasSize() {
            gCanvasMetrics.width = window.innerWidth;
            gCanvasMetrics.height = window.innerHeight;

            $canvas.width = gCanvasMetrics.width;
            $canvas.height = gCanvasMetrics.height;
            console.log('Canvas size is set to ' + gCanvasMetrics.width + 'x' + gCanvasMetrics.height);

            gCanvasMetrics.scaleFactor = Math.min(gCanvasMetrics.width/gCanvasMetrics.DEFAULT_WIDTH,
                                                 gCanvasMetrics.height/gCanvasMetrics.DEFAULT_HEIGHT);
            console.log('Scale factor is set to ' + gCanvasMetrics.scaleFactor);

            gCanvasMetrics.offsetX = Math.floor((gCanvasMetrics.width - gCanvasMetrics.DEFAULT_WIDTH*gCanvasMetrics.scaleFactor)/2);
            gCanvasMetrics.offsetY = Math.floor((gCanvasMetrics.height - gCanvasMetrics.DEFAULT_HEIGHT*gCanvasMetrics.scaleFactor)/2);
            console.log('Offsets: x=' + gCanvasMetrics.offsetX + ', y=' + gCanvasMetrics.offsetY);

            gCtx.setTransform(gCanvasMetrics.scaleFactor, 0, 0, gCanvasMetrics.scaleFactor, gCanvasMetrics.offsetX, gCanvasMetrics.offsetY);
        }

        function setButtonsPosition() {
            for (var i = 0, len = gButtons.length; i < len; i++) {
                gSetButtonPosition(gButtons[i]);
            }
        }
    }

    function gSetButtonPosition(aButton) {
        var xFactor = gImagesPaths.length > 1 ? 0.1 + 0.8*aButton.number/(gImagesPaths.length - 1) : 0.5;
        aButton.style.top = gCanvasMetrics.height*0.8 + 'px';
        aButton.style.left = (gCanvasMetrics.offsetX + gCanvasMetrics.scaleFactor*gCanvasMetrics.DEFAULT_WIDTH*xFactor) + 'px';
    }

    function gStartImagesLoading() {
        for (var i = 0, len = gImagesPaths.length; i < len; i++) {
            gImages[i] = new Image();
            gImages[i].onload = addButtonForImage.bind(null, i);
            gImages[i].src = gImagesPaths[i];
        }

        function addButtonForImage(aNumber) {
            console.log('Image ' + aNumber + ' is loaded.');

            var $button = document.createElement('button');
            $button.className = 'image_button';
            $button.textContent = 'Image ' + (aNumber + 1);
            $button.number = aNumber;
            gSetButtonPosition($button);
            $buttonsContainer.insertBefore($button, null);
            $button.onclick = buttonClickAction.bind(null, aNumber);

            gButtons.push($button);
        }

        function buttonClickAction(aNumber) {
            var lastImageOnStack, index = getIndexOfImageOnStack(aNumber);

            if (~index) {
                gClearAreaOfImageWithIndex(index);
                // Remove image from canvas image stack array.
                gImagesOnCanvasStack = gImagesOnCanvasStack.slice(0, index).concat(gImagesOnCanvasStack.slice(index + 1));
            } else {
                lastImageOnStack = gImagesOnCanvasStack.length ? gImagesOnCanvasStack[gImagesOnCanvasStack.length - 1] : null;
                gImagesOnCanvasStack.push({
                    x: lastImageOnStack ? lastImageOnStack.x + gImagesMetrics.OFFSET_X : (gCanvasMetrics.DEFAULT_WIDTH - gImagesMetrics.DEFAULT_WIDTH)/2,
                    y: lastImageOnStack ? lastImageOnStack.y + gImagesMetrics.OFFSET_Y : (gCanvasMetrics.DEFAULT_HEIGHT - gImagesMetrics.DEFAULT_HEIGHT)/2,
                    imageNo: aNumber
                });
            }
            gDraw();
        }

        function getIndexOfImageOnStack(aNumber) {
            for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
                if (gImagesOnCanvasStack[i].imageNo === aNumber) {
                    return i;
                }
            }
            return -1;
        }
    }

    function gDraw() {
        var currentImage;
        for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
            currentImage = gImagesOnCanvasStack[i];
            gCtx.drawImage(gImages[currentImage.imageNo], currentImage.x, currentImage.y);
        }
    }

    function gCalculateCanvasCoordsFromMouseEvent(aMouseEvent) {
        var x = (aMouseEvent.clientX - gCanvasMetrics.offsetX)/gCanvasMetrics.scaleFactor,
            y = (aMouseEvent.clientY - gCanvasMetrics.offsetY)/gCanvasMetrics.scaleFactor;
        return { x: x, y: y };
    }

    function gGetIndexOfImageUnderMouse(aX, aY) {
        var currentImage;
        for (var i = gImagesOnCanvasStack.length - 1; i >= 0; i--) {
            currentImage = gImagesOnCanvasStack[i];
            if (aX >= currentImage.x && aX <= currentImage.x + gImagesMetrics.DEFAULT_WIDTH &&
                aY >= currentImage.y && aY <= currentImage.y + gImagesMetrics.DEFAULT_HEIGHT) {
                return i;
            }
        }
        return -1;
    }

    function gClearAreaOfImageWithIndex(aIndex) {
        var image = gImagesOnCanvasStack[aIndex];
        gCtx.clearRect(
            image.x - gImagesMetrics.ADDITION,
            image.y - gImagesMetrics.ADDITION,
            gImagesMetrics.DEFAULT_WIDTH + 2*gImagesMetrics.ADDITION,
            gImagesMetrics.DEFAULT_HEIGHT + 2*gImagesMetrics.ADDITION
        );
    }

    function gCanvasOnMouseMoveAction(aMouseEvent) {
        if (~gCurrentDraggingImageIndex && !gIsAnimationFrameRequested) {
            gIsAnimationFrameRequested = true;
            gMouseEvent = aMouseEvent;
            window.requestAnimationFrame(gMoveDraggingImageAndRedraw.bind(null, gCurrentDraggingImageIndex));
        }
    }

    function gMoveDraggingImageAndRedraw(aIndex) {
        gIsAnimationFrameRequested = false;

        var currentCoords = gCalculateCanvasCoordsFromMouseEvent(gMouseEvent);

        gClearAreaOfImageWithIndex(aIndex);

        gImagesOnCanvasStack[aIndex].x += currentCoords.x - gLastCoords.x;
        gImagesOnCanvasStack[aIndex].y += currentCoords.y - gLastCoords.y;

        gLastCoords.x = currentCoords.x;
        gLastCoords.y = currentCoords.y;

        gDraw();
    }
})();<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import { fetchBlocks, isBlocksLoaded } from '../../reducers/blocks'
import { actions as blockActions } from '../../../modules/mobilizations/blocks'
import { fetchWidgets, isWidgetsLoaded } from '../../Widget/reducer'
import { getMobilization } from '../MobilizationSelectors'
import { setCurrentMobilizationId } from '../MobilizationActions'
import { GoogleFontsLoader } from '../../../components/Fonts'
import * as arrayUtil from '../../../util/array'

const { asyncBlockFetch } = blockActions

class MobilizationDashboardContainer extends React.Component {
  static propTypes = {
    blocks: PropTypes.object.isRequired,
    widgets: PropTypes.object.isRequired,
    dispatch: PropTypes.func.isRequired,
    mobilization: PropTypes.object.isRequired,
    auth: PropTypes.object.isRequired,
    children: PropTypes.object
  }

  static fetchData(store, params) {
    const promises = []
    if (!isBlocksLoaded(store.getState())) {
      const action = asyncBlockFetch(params.mobilization_id)
      const promise = store.dispatch(action)
      promises.push(promise)
    }
    if (!isWidgetsLoaded(store.getState())) {
      const action = fetchWidgets({mobilization_id: params.mobilization_id})
      const promise = store.dispatch(action)
      promises.push(promise)
    }
    return Promise.all(promises)
  }

  componentDidMount() {
    // TODO this callback is a workaround to load data in client-side
    // but it should be replaced by the static fetchData method that is fetching
    // data only in the server-side for now
    const {dispatch, mobilization} = this.props
    dispatch(asyncBlockFetch(mobilization.id))
    dispatch(fetchWidgets({mobilization_id: mobilization.id}))
    dispatch(setCurrentMobilizationId(mobilization.id))
  }

  render() {
    const { children, ...otherProps } = this.props
    const { mobilization: { header_font: headerFont, body_font: bodyFont } } = otherProps
    const fonts = [headerFont, bodyFont].filter(arrayUtil.distinct)

    return (

        {children && React.cloneElement(children, {...otherProps})}
        <GoogleFontsLoader fonts={fonts} />

    )
  }
}

const mapStateToProps = (state, props) => ({
  auth: state.auth,
  blocks: state.blocks,
  widgets: state.widgets,
  mobilization: getMobilization(state, props)
})

export default connect(mapStateToProps)(MobilizationDashboardContainer)
<commit_msg>Remove remaining uses of fetchBlocks action #275<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import { isBlocksLoaded } from '../../reducers/blocks'
import { actions as blockActions } from '../../../modules/mobilizations/blocks'
import { fetchWidgets, isWidgetsLoaded } from '../../Widget/reducer'
import { getMobilization } from '../MobilizationSelectors'
import { setCurrentMobilizationId } from '../MobilizationActions'
import { GoogleFontsLoader } from '../../../components/Fonts'
import * as arrayUtil from '../../../util/array'

const { asyncBlockFetch } = blockActions

class MobilizationDashboardContainer extends React.Component {
  static propTypes = {
    blocks: PropTypes.object.isRequired,
    widgets: PropTypes.object.isRequired,
    dispatch: PropTypes.func.isRequired,
    mobilization: PropTypes.object.isRequired,
    auth: PropTypes.object.isRequired,
    children: PropTypes.object
  }

  static fetchData(store, params) {
    const promises = []
    if (!isBlocksLoaded(store.getState())) {
      const action = asyncBlockFetch(params.mobilization_id)
      const promise = store.dispatch(action)
      promises.push(promise)
    }
    if (!isWidgetsLoaded(store.getState())) {
      const action = fetchWidgets({mobilization_id: params.mobilization_id})
      const promise = store.dispatch(action)
      promises.push(promise)
    }
    return Promise.all(promises)
  }

  componentDidMount() {
    // TODO this callback is a workaround to load data in client-side
    // but it should be replaced by the static fetchData method that is fetching
    // data only in the server-side for now
    const {dispatch, mobilization} = this.props
    dispatch(asyncBlockFetch(mobilization.id))
    dispatch(fetchWidgets({mobilization_id: mobilization.id}))
    dispatch(setCurrentMobilizationId(mobilization.id))
  }

  render() {
    const { children, ...otherProps } = this.props
    const { mobilization: { header_font: headerFont, body_font: bodyFont } } = otherProps
    const fonts = [headerFont, bodyFont].filter(arrayUtil.distinct)

    return (

        {children && React.cloneElement(children, {...otherProps})}
        <GoogleFontsLoader fonts={fonts} />

    )
  }
}

const mapStateToProps = (state, props) => ({
  auth: state.auth,
  blocks: state.blocks,
  widgets: state.widgets,
  mobilization: getMobilization(state, props)
})

export default connect(mapStateToProps)(MobilizationDashboardContainer)
<|endoftext|>


<commit_before>// constants
var personWidth = 30
var personHeight = 20
var childPad = 20
var siblingPad = 5
var svgPad = 3

var families = {}
var persons = {}

/*
 ----------------------------------------------------------------------
  Data Model
 ----------------------------------------------------------------------
*/

function getFamily(id) {
    var family = families[id]
    if (family == null) {
        family = {
            "id": id,
            "parents":[],
            "children":[],
        }
        families[id] = family
    }
    return family
}

function getFamilyDimensions(id) {
    var family = getFamily(id)
    var w = 0
    var h = 0
    if (0 < family.children.length) {
        w += childPad
        var mw = 0
        for (var i = 0; i < family.children.length; i++) {
            var child = family.children[i]
            if (0 < h) h += siblingPad
            var cd = getPersonDimensions(child)
            if (mw < cd[0]) mw = cd[0]
            h += cd[1]
        }
        w += mw
    }
    return [w, h]
}

function getPersonDimensions(id) {
    var person = persons[id]
    var d = [personWidth, personHeight]
    var famsDims = [0, 0]
    for (var i = 0; i < person.parentOf.length; i++) {
        var famDim = getFamilyDimensions(person.parentOf[i])
        if (famDim != null){
            famsDims[0] = Math.max(famsDims[0], famDim[0])
            famsDims[1] += famDim[1]
        }
    }
    return [d[0] + famsDims[0], Math.max(d[1], famsDims[1])]
}

function hasChildren(id) {
    var person = persons[id]
    for (var i = 0; i < person.parentOf.length; i++) {
        var family = getFamily(person.parentOf[i])
        if (0 < family.children.length) return true
    }
    return false
}

function getChildren(id) {
    var person = persons[id]
    var children = []
    for (var i = 0; i < person.parentOf.length; i++) {
        children = children.concat(getFamily(person.parentOf[i]).children)
    }
    return children
}

function Person(id, name, gender, childOf, parentOf) {
    var person = persons[id]
    if (person != null) {
        return
    }
    person = {
        "id": id,
        "name": name,
        "gender": gender,
        "childOf": canonicalizeMemberOf(childOf),
        "parentOf": canonicalizeMemberOf(parentOf),
    }
    persons[id] = person
    for (var i = 0; i < person.childOf.length; i++) {
        getFamily(person.childOf[i]).children.push(id)
    }
    for (var i = 0; i < person.parentOf.length; i++) {
        getFamily(person.parentOf[i]).parents.push(id)
    }
}

function canonicalizeMemberOf(obj) {
    if (Array.isArray(obj)) {
        return obj
    }
    if (obj == null) {
        return []
    }
    return [obj]
}

/*
 ----------------------------------------------------------------------
  SVG Rendering
 ----------------------------------------------------------------------
*/

function render(personId) {
    var dims = getPersonDimensions(personId)
    var svg = document.getElementById("cnv")
    svg.setAttribute("width", dims[0] + svgPad * 2)
    svg.setAttribute("height", dims[1] + svgPad * 2)
    renderTree(personId, [svgPad, dims[1] / 2 - personHeight / 2 + svgPad])
}

function renderTree(personId, offset){
    renderPerson(personId, offset)
    if (!hasChildren(personId)) {
        return
    }
    dims = getPersonDimensions(personId)
    var foffset = [offset[0] + personWidth + childPad, offset[1]]
    // TODO: multifamily
    renderFamily(persons[personId].parentOf[0], foffset)
}

var svgns = "http://www.w3.org/2000/svg"

function renderPerson(id, offset) {
    var person = persons[id]
    var svg = document.getElementById("cnv")
    var rect = document.createElementNS(svgns, "rect");
    rect.setAttribute("x", offset[0]);
    rect.setAttribute("y", offset[1]);
    rect.setAttribute("rx", 5);
    rect.setAttribute("ry", 5);
    rect.setAttribute("width", personWidth);
    rect.setAttribute("height", personHeight);
    rect.setAttribute("stroke", "green");
    if (person.gender == "m") {
        rect.setAttribute("fill", "#abcdef")
    }else{
        rect.setAttribute("fill", "#fedcba")
    }
    var text = document.createElementNS(svgns, "text");
    text.setAttribute("x", offset[0] + 3);
    text.setAttribute("y", offset[1] + personHeight - 5);
    text.innerHTML = person.name
    svg.appendChild(rect)
    svg.appendChild(text)
}

function renderFamily(id, offset) {
    var svg = document.getElementById("cnv")
    var family = getFamily(id)
    var famDims = getFamilyDimensions(id)
    var hoffset = offset[1] - famDims[1] / 2
    for (var i = 0; i < family.children.length; i++) {
        var child = family.children[i]
        var childDims = getPersonDimensions(child)
        renderTree(child, [offset[0], hoffset + childDims[1] / 2])
        var line = document.createElementNS(svgns, "line");
        line.setAttribute("x1", offset[0] - childPad);
        line.setAttribute("y1", offset[1] + personHeight / 2);
        line.setAttribute("x2", offset[0]);
        line.setAttribute("y2", hoffset + childDims[1] / 2 + personHeight / 2);
        line.setAttribute("style", "stroke:silver;stroke-width:2")
        svg.appendChild(line)
        hoffset += childDims[1] + siblingPad
    }
}
<commit_msg>group functions<commit_after>// constants
var personWidth = 30
var personHeight = 20
var childPad = 20
var siblingPad = 5
var svgPad = 3

var families = {}
var persons = {}

/*
 ----------------------------------------------------------------------
  Data Model
 ----------------------------------------------------------------------
*/

function Person(id, name, gender, childOf, parentOf) {
    var person = persons[id]
    if (person != null) {
        return
    }
    person = {
        "id": id,
        "name": name,
        "gender": gender,
        "childOf": canonicalizeMemberOf(childOf),
        "parentOf": canonicalizeMemberOf(parentOf),
    }
    persons[id] = person
    for (var i = 0; i < person.childOf.length; i++) {
        getFamily(person.childOf[i]).children.push(id)
    }
    for (var i = 0; i < person.parentOf.length; i++) {
        getFamily(person.parentOf[i]).parents.push(id)
    }
}

// ----------------------------------------------------------------------
// Getters

function getFamily(id) {
    var family = families[id]
    if (family == null) {
        family = {
            "id": id,
            "parents":[],
            "children":[],
        }
        families[id] = family
    }
    return family
}

function hasChildren(id) {
    var person = persons[id]
    for (var i = 0; i < person.parentOf.length; i++) {
        var family = getFamily(person.parentOf[i])
        if (0 < family.children.length) return true
    }
    return false
}

function getChildren(id) {
    var person = persons[id]
    var children = []
    for (var i = 0; i < person.parentOf.length; i++) {
        children = children.concat(getFamily(person.parentOf[i]).children)
    }
    return children
}

function getPartner(personId, familyId) {
    var family = families[familyId]
    for (var i = 0; i < family.parents.length; i++) {
        var parent = family.parents[i]
        if (parent != personId) {
            return parent
        }
    }
    return null
}

function canonicalizeMemberOf(obj) {
    if (Array.isArray(obj)) {
        return obj
    }
    if (obj == null) {
        return []
    }
    return [obj]
}

/*
 ----------------------------------------------------------------------
  Dimensions calculation
 ----------------------------------------------------------------------
*/

function getPersonDimensions(id) {
    var person = persons[id]
    var d = [personWidth, personHeight]
    var famsDims = [0, 0]
    for (var i = 0; i < person.parentOf.length; i++) {
        var famDim = getFamilyDimensions(person.parentOf[i])
        if (famDim != null){
            famsDims[0] = Math.max(famsDims[0], famDim[0])
            famsDims[1] += famDim[1]
        }
    }
    return [d[0] + famsDims[0], Math.max(d[1], famsDims[1])]
}

function getFamilyDimensions(id) {
    var family = getFamily(id)
    var w = 0
    var h = 0
    if (0 < family.children.length) {
        w += childPad
        var mw = 0
        for (var i = 0; i < family.children.length; i++) {
            var child = family.children[i]
            if (0 < h) h += siblingPad
            var cd = getPersonDimensions(child)
            if (mw < cd[0]) mw = cd[0]
            h += cd[1]
        }
        w += mw
    }
    return [w, h]
}

/*
 ----------------------------------------------------------------------
  SVG Rendering
 ----------------------------------------------------------------------
*/

function render(personId) {
    var dims = getPersonDimensions(personId)
    var svg = document.getElementById("cnv")
    svg.setAttribute("width", dims[0] + svgPad * 2)
    svg.setAttribute("height", dims[1] + svgPad * 2)
    renderTree(personId, [svgPad, dims[1] / 2 - personHeight / 2 + svgPad])
}

function renderTree(personId, offset){
    renderPerson(personId, offset)
    if (!hasChildren(personId)) {
        return
    }
    dims = getPersonDimensions(personId)
    var foffset = [offset[0] + personWidth + childPad, offset[1]]
    // TODO: multifamily
    renderFamily(persons[personId].parentOf[0], foffset)
}

var svgns = "http://www.w3.org/2000/svg"

function renderPerson(id, offset) {
    var person = persons[id]
    var svg = document.getElementById("cnv")
    var rect = document.createElementNS(svgns, "rect");
    rect.setAttribute("x", offset[0]);
    rect.setAttribute("y", offset[1]);
    rect.setAttribute("rx", 5);
    rect.setAttribute("ry", 5);
    rect.setAttribute("width", personWidth);
    rect.setAttribute("height", personHeight);
    rect.setAttribute("stroke", "green");
    if (person.gender == "m") {
        rect.setAttribute("fill", "#abcdef")
    }else{
        rect.setAttribute("fill", "#fedcba")
    }
    var text = document.createElementNS(svgns, "text");
    text.setAttribute("x", offset[0] + 3);
    text.setAttribute("y", offset[1] + personHeight - 5);
    text.innerHTML = person.name
    svg.appendChild(rect)
    svg.appendChild(text)
}

function renderFamily(id, offset) {
    var svg = document.getElementById("cnv")
    var family = getFamily(id)
    var famDims = getFamilyDimensions(id)
    var hoffset = offset[1] - famDims[1] / 2
    for (var i = 0; i < family.children.length; i++) {
        var child = family.children[i]
        var childDims = getPersonDimensions(child)
        renderTree(child, [offset[0], hoffset + childDims[1] / 2])
        var line = document.createElementNS(svgns, "line");
        line.setAttribute("x1", offset[0] - childPad);
        line.setAttribute("y1", offset[1] + personHeight / 2);
        line.setAttribute("x2", offset[0]);
        line.setAttribute("y2", hoffset + childDims[1] / 2 + personHeight / 2);
        line.setAttribute("style", "stroke:silver;stroke-width:2")
        svg.appendChild(line)
        hoffset += childDims[1] + siblingPad
    }
}
<|endoftext|>


<commit_before>//    Aebleskiver
//    (c) 2011 Beau Sorensen
//    Aebleskiver may be freely distributed under the MIT license.
//    For all details and documentation:
//    https://github.com/sorensen/aebleskiver

// Clustered server
// ----------------

var Cluster  = require('cluster'),
    Live     = require('cluster-live'),
    Mongoose = require('mongoose');

// Connect to the database
Mongoose.connect('mongodb://localhost/aebleskiver');

// Start the cluster
Cluster('./app')
    .set('socket path', __dirname + '/socks')
    .use(Cluster.logger(__dirname + '/logs'))
    .use(Cluster.pidfiles(__dirname + '/pids'))
    .set('workers', 4)
    .in('development')
        .listen(8080)
        .use(Cluster.cli())
        .use(Cluster.repl(8000))
        .use(Cluster.debug())
        .use(Cluster.reload(['lib', 'vendor', 'app.js']))
        .use(Cluster.stats({
            connections   : true,
            lightRequests : true
        }))
        .use(Live({
            port : 8888,
            host : 'localhost',
            user : '',
            pass : ''
        }))
    .in('production')
        .use(Live({
            user : 'admin',
            pass : 'aebleskiver'
        }))
        .listen(80);<commit_msg>Updating cluster configuration.<commit_after>//    Aebleskiver
//    (c) 2011 Beau Sorensen
//    Aebleskiver may be freely distributed under the MIT license.
//    For all details and documentation:
//    https://github.com/sorensen/aebleskiver

// Clustered server
// ----------------

var Cluster  = require('cluster'),
    Live     = require('cluster-live'),
    Mongoose = require('mongoose');

// Start the cluster
Cluster('./app')
    .set('socket path', __dirname + '/socks')
    .use(Cluster.logger(__dirname + '/logs'))
    .use(Cluster.pidfiles(__dirname + '/pids'))
    .set('workers', 4)
    .in('development')
        .listen(8080)
        .use(Cluster.cli())
        .use(Cluster.repl(8000))
        .use(Cluster.debug())
        .use(Cluster.reload(['lib', 'vendor', 'app.js']))
        .use(Cluster.stats({
            connections   : true,
            lightRequests : true
        }))
        .use(Live({
            port : 8888,
            host : 'localhost',
            user : '',
            pass : ''
        }))
    .in('production')
        .use(Cluster.stats({
            connections   : true,
            lightRequests : true
        }))
        .use(Live({
            user : 'admin',
            pass : 'aebleskiver'
        }))
        .listen(80);<|endoftext|>


<commit_before>$(document).ready(function ($) {
    $.fn.mood = function () {
        var i, moods = ['happy', 'neutral', 'sad'];
        for (i = 0; i < moods.length; i++) {
            if (this.hasClass(moods[i])) { return moods[i]; }
        }
        return null;
    }

    $.fn.updateIndicator = function () {
        var mood = this.mood();
        if (mood) { document.querySelector('link[rel="icon"]').setAttribute('href', chrome.extension.getURL(mood + '.png')); }
        return this;
    }

		// create an observer
		var
		updateIndicatorOnClassMutation = function (mutation) {
			if (mutation.type === 'attributes' && mutation.attributeName === 'class' ) {
				$(mutation.target).updateIndicator();
			}
		},
		observer = new MutationObserver(function(mutations) {
			mutations.forEach(this);
		}.bind(updateIndicatorOnClassMutation));
		// observe happiness
		observer.observe(document.getElementById('happiness'), {attributes: true});
		$('#happiness').updateIndicator();

});
<commit_msg>detach updateIndicator from jquery<commit_after>$(document).ready(function ($) {
    $.fn.mood = function () {
        var i, moods = ['happy', 'neutral', 'sad'];
        for (i = 0; i < moods.length; i++) {
            if (this.hasClass(moods[i])) { return moods[i]; }
        }
        return null;
    }

     function updateIndicator (el) {
        var mood = $(el).mood();
        if (mood) { icon.setAttribute('href', chrome.extension.getURL(mood + '.png')); }
    }

		// create an observer
		var
		happiness = document.getElementById('happiness'),
		icon = document.querySelector('link[rel="icon"]'),
		updateIndicatorOnClassMutation = function (mutation) {
			if (mutation.type === 'attributes' && mutation.attributeName === 'class' ) {
				updateIndicator(mutation.target);
			}
		},
		observer = new MutationObserver(function(mutations) {
			mutations.forEach(this);
		}.bind(updateIndicatorOnClassMutation));
		// observe happiness
		observer.observe(happiness, {attributes: true});
		updateIndicator(happiness);

});
<|endoftext|>