<commit_before>$(document).ready(function($){
    $('#fileinput').on('change', function(event) {
        readMultipleFiles(event);
    });
});

function readMultipleFiles(event) {
    $('#wrap').empty();
    //Retrieve all the files from the FileList object
    var files = event.target.files,
        output = $("#wrap");

    if (files) {
        for (var i = 0, f; f = files[i]; i++) {
            var reader = new FileReader();
            reader.onload = (function (f) {
                return function (e) {
                    var contents = e.target.result,
                        filename = f.name,
                        extension = filename.substr( (filename.lastIndexOf('.') +1) );

                    $('#wrap').append('filename: ' + filename + '
');
                    $('#wrap').append('extension: ' + extension + '
');

                    //console.log('contents: ', contents);

                    // choose the right parser
                    switch(extension) {

                        case 'm3u':
                            parseM3u(contents);
                            break;
                        case 'pls':

                            break;
                        case 'txt':

                            break;

                        case 'xml': // Native Instruments: Traktor
                            parseXml(contents);
                            break;
                        case 'nml': // Native Instruments: Traktor
                            parseXml(contents);
                            break;
                        case 'asx': // Windows Media Player

                            break;
                        case 'wpl': // Windows Media Player

                            break;
                    }
                };
            })(f);
            reader.readAsText(f);
        }
    } else {
        alert("Failed to load files");
    }
}

var parseXml = function(contents) {
    var i = 0, j = i,
        xml = $.parseXML(contents),
        fileFilter = 'ENTRY',
        fileArtist = '',
        fileTitle = '';

    $(xml).find(fileFilter).each(function() {
        // extract the needed content
        fileArtist = $(this).attr('ARTIST');
        fileTitle = $(this).attr('TITLE');

        // only execute if artis or title are present
        if(fileArtist || fileTitle) {
            i++;
            j = (i < 10 ? j = '0' + i : j = i);
            // append it to the DOM
            sendOutput(i, j, fileArtist, fileTitle);
        }
    });
}

var parseM3u = function(contents) {
    var i = 0, j = i, k = i,
        m3u = contents,
        fileComment = '#EXTINF',
        fileArtist = '',
        fileTitle = '',
        fileLine = '',
        currLine = '',
        outLine = '',
        lines = '';

    // Regular expressions
    var lineEx = /[\r\n]+/g, // tolerate both Windows and Unix linebreaks
        matchEx = /([^,]*),(.*)/m,
        splitEx = /-(.+)?/;

    // let's go!
    lines = m3u.split(lineEx);
    for(i; i < lines.length; i++) {
        fileLine = lines[i].indexOf(fileComment);
        if (fileLine === 0) {
            k++;
            j = (k < 10 ? j = '0' + k : j = k);
            currLine = lines[i].match(matchEx);
            outLine = currLine[2];
            fileArtist = outLine.split(splitEx)[0];
            fileTitle = outLine.split(splitEx)[1];
            // append it to the DOM
            sendOutput(k, j, fileArtist, fileTitle);
        }
    }
}

var sendOutput = function(i, j, artist, title) {
    var fileOutput = '';
    fileOutput += j + '. - ';
    fileOutput += '<input type="text" name="artist" id="+i+" value="' + artist.trim() + '">';
    fileOutput += ' - ';
    fileOutput += '<input type="text" name="title" id="+i+" value="' + title.trim() + '">';
    fileOutput += '
';
    $('#wrap').append(fileOutput);
}

/*
--- m3u working example - Extended M3U ---
#EXTM3U
#EXTINF:123, Sample artist - Sample title
C:\Documents and Settings\I\My Music\Sample.mp3
#EXTINF:321,Example Artist - Example title
C:\Documents and Settings\I\My Music\Greatest Hits\Example.ogg
*/
<commit_msg>new parsers added: *.wpl *.asx *.pls<commit_after>$(document).ready(function($){
    $('#fileinput').on('change', function(event) {
        readMultipleFiles(event);
    });
});

// Global vars
var fileArtist = '',
    fileTitle = '';

var readMultipleFiles = function(event) {
    $('#wrap').empty();
    // Retrieve all the files from the FileList object
    var files = event.target.files,
        output = $("#wrap");

    if (files) {
        for (var i = 0, f; f = files[i]; i++) {
            var reader = new FileReader();
            reader.onload = (function (f) {
                return function (e) {
                    var contents = e.target.result,
                        filename = f.name,
                        extension = filename.substr((filename.lastIndexOf('.')+1));

                    $('#wrap').append('filename: ' + filename + '
');
                    $('#wrap').append('extension: ' + extension + '
');

                    // Choose the right parser
                    switch(extension) {
                        case 'm3u':
                            parseM3u(contents);
                            break;
                        case 'pls':
                            parsePls(contents);
                            break;
                        case 'txt':

                            break;
                        case 'xml': // Native Instruments: Traktor
                            parseXml(contents, extension);
                            break;
                        case 'nml': // Native Instruments: Traktor
                            parseXml(contents, extension);
                            break;
                        case 'asx': // Windows Media Player
                            parseXml(contents, extension);
                            break;
                        case 'wpl': // Windows Media Player
                            parseWpl(contents);
                            break;
                    }
                };
            })(f);
            reader.readAsText(f);
        }
    } else {
        alert("Failed to load files");
    }
}

var parseXml = function(contents, extension) {
    var i = 0, j = i,
        fileFilter = 'entry';

    $(contents).find(fileFilter).each(function() {
        // Choose the right content parser
        switch(extension) {
            case 'asx': // Windows Media Player
                // Extract the needed content
                fileArtist = $(this).find('author').text();
                fileTitle = $(this).find('title').text();
                break;
            default: // Native Instruments: Traktor
                // Extract the needed content
                fileArtist = $(this).attr('artist');
                fileTitle = $(this).attr('title');
                break;
        }
        // Only execute if artis or title are present
        if(fileArtist || fileTitle) {
            i++;
            j = (i < 10 ? j = '0' + i : j = i);
            // Append it to the DOM
            sendOutput(i, j, fileArtist, fileTitle);
        }
    });
}

var parseWpl = function(contents) {
    var i = 0, j = i,
        fileFilter = 'media',
        lineFilter = '',
        outLine = '';

    var splitEx = /-(.+)?/,
        uscoreEx = /_/g,
        extensionEx = /.mp3|.wma|.wav|.3gp|.aiff|.flac|.m4a|.ogg|.ra|.rm/gi;

    $(contents).find(fileFilter).each(function() {
        // Extract the needed content
        lineFilter = $(this).attr('src');

        outLine = lineFilter.substring(lineFilter.lastIndexOf('\\') + 1, lineFilter.length).replace(uscoreEx, ' ');
        fileArtist = outLine.split(splitEx)[0];
        fileTitle = outLine.split(splitEx)[1].replace(extensionEx,'');;

        // Only execute if artis or title are present
        if(fileArtist || fileTitle) {
            i++;
            j = (i < 10 ? j = '0' + i : j = i);
            // Append it to the DOM
            sendOutput(i, j, fileArtist, fileTitle);
        }
    });
}

var parseM3u = function(contents) {
    var i = 0, j = i, k = i,
        fileComment = '#extinf',
        fileLine = '',
        currLine = '',
        outLine = '',
        lines = '';

    // Regular expressions
    var lineEx = /[\r\n]+/g, // tolerate both Windows and Unix linebreaks
        matchEx = /([^,]*),(.*)/m,
        splitEx = /-(.+)?/;

    // Let's go!
    lines = contents.split(lineEx);
    for(i; i < lines.length; i++) {
        fileLine = lines[i].toLowerCase().indexOf(fileComment);
        if (fileLine === 0) {
            k++;
            j = (k < 10 ? j = '0' + k : j = k);
            currLine = lines[i].match(matchEx);
            outLine = currLine[2];
            fileArtist = outLine.split(splitEx)[0];
            fileTitle = outLine.split(splitEx)[1];
            // Append it to the DOM
            sendOutput(k, j, fileArtist, fileTitle);
        }
    }
}

var parsePls = function(contents) {
    var i = 0, j = i, k = i,
        fileComment = 'title',
        fileLine = '',
        currLine = '',
        outLine = '',
        lines = '';

    // Regular expressions
    var lineEx = /[\r\n]+/g, // tolerate both Windows and Unix linebreaks
        matchEx = /([^,]*)=(.*)/m,
        uscoreEx = /_/g,
        splitEx = /-(.+)?/;

    // Let's go!
    lines = contents.split(lineEx);
    for(i; i < lines.length; i++) {
        fileLine = lines[i].toLowerCase().indexOf(fileComment);
        if (fileLine === 0) {
            k++;
            j = (k < 10 ? j = '0' + k : j = k);
            currLine = lines[i].match(matchEx);
            outLine = currLine[2].replace(uscoreEx, ' ');
            fileArtist = outLine.split(splitEx)[0];
            fileTitle = outLine.split(splitEx)[1];
            // Append it to the DOM
            sendOutput(k, j, fileArtist, fileTitle);
        }
    }
}

// Send to HTML
var sendOutput = function(i, j, artist, title) {
    var fileOutput = '';
    fileOutput += j + '. - ';
    fileOutput += '<input type="text" name="artist" id="+i+" value="' + artist.trim() + '">';
    fileOutput += ' - ';
    fileOutput += '<input type="text" name="title" id="+i+" value="' + title.trim() + '">';
    fileOutput += '
';
    $('#wrap').append(fileOutput);
}

/*
--- *.m3u working example - Extended M3U ---
#EXTM3U
#EXTINF:123, Sample artist - Sample title
C:\Documents and Settings\I\My Music\Sample.mp3
#EXTINF:321,Example Artist - Example title
C:\Documents and Settings\I\My Music\Greatest Hits\Example.ogg
*/
<|endoftext|>


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

define([
    'hft/misc/misc',
    'hft/misc/strings',
    '../bower_components/hft-utils/dist/2d',
    '../bower_components/hft-utils/dist/imageutils',
  ], function(
    Misc,
    Strings,
    M2D,
    ImageUtils) {

  var availableColors = [];
  var nameFontOptions = {
    font: "20px sans-serif",
    yOffset: 18,
    height: 20,
    fillStyle: "black",
  };

  /**
   * Player represnt a player in the game.
   * @constructor
   */
  var Player = (function() {
    return function(services, width, height, direction, name, netPlayer) {
      this.services = services;
      this.renderer = services.renderer;
      services.entitySystem.addEntity(this);
      services.drawSystem.addEntity(this);
      this.netPlayer = netPlayer;
      this.velocity = [0, 0];
      this.acceleration = [0, 0];
      if (availableColors.length == 0) {
        var colors = services.colors;
        for (var ii = 0; ii < colors.length; ++ii) {
          availableColors.push(colors[ii]);
        }
      }
      var colorNdx = Math.floor(Math.random() * availableColors.length);
      this.color = availableColors[colorNdx];
window.p = this;
      netPlayer.sendCmd('setColor', this.color);
      availableColors.splice(colorNdx, 1);
      this.color.id;
      this.animTimer = 0;
      this.width = width;
      this.height = height;
      this.canJump = false;
      this.checkWallOffset = [
        -this.width / 2,
        this.width / 2 - 1,
      ];
      this.timeAccumulator = 0;

      this.scoreLine = this.services.scoreManager.createScoreLine(this, this.color);
      this.scoreLine.ctx.drawImage(
        this.services.images.idle.imgColors[this.color.id][0], 0, 0);

      this.sprite = this.services.spriteManager.createSprite();
      this.nameSprite = this.services.spriteManager.createSprite();

      netPlayer.addEventListener('disconnect', Player.prototype.handleDisconnect.bind(this));
      netPlayer.addEventListener('move', Player.prototype.handleMoveMsg.bind(this));
      netPlayer.addEventListener('jump', Player.prototype.handleJumpMsg.bind(this));
      netPlayer.addEventListener('setName', Player.prototype.handleNameMsg.bind(this));
      netPlayer.addEventListener('busy', Player.prototype.handleBusyMsg.bind(this));
      netPlayer.addEventListener('word choice', Player.prototype.handleWordChoiceMsg.bind(this));

      this.setName(name);
      this.direction = 0;         // direction player is pushing (-1, 0, 1)
      this.facing = direction;    // direction player is facing (-1, 1)
      this.score = 0;
      this.addPoints(0);

      this.setState('idle');
      this.reset();
      this.checkBounds();
    };
  }());

  Player.prototype.setName = function(name) {
    if (name != this.playerName) {
      this.playerName = name;
      this.nameImage = this.services.createTexture(
          ImageUtils.makeTextImage(name, nameFontOptions));
      this.scoreLine.setName(":" + name);
    }
  };

  Player.prototype.reset = function() {
    var levelManager = this.services.levelManager;
    var level = levelManager.getLevel();
    var position = levelManager.getRandomOpenPosition();
    this.position = [position.x, position.y];
    this.lastPosition = [this.position[0], this.position[1]];
  };

  Player.prototype.addPoints = function(points) {
    this.score += points;
    this.scoreLine.setMsg(Strings.padLeft(this.score, 3, "0"));
  };

  Player.prototype.setState = function(state) {
    this.state = state;
    var init = this["init_" + state];
    if (init) {
      init.call(this);
    }
    this.process = this["state_" + state];
  };

  Player.prototype.checkBounds = function() {
    var levelManager = this.services.levelManager;
    var level = levelManager.getLevel();

    if (this.position[1] > level.width * level.tileHeight) {
      debugger;
    }
  };

  Player.prototype.checkJump = function() {
    if (this.canJump) {
      if (this.jump) {
        this.canJump = false;
        this.setState('jump');
      }
    } else {
      if (!this.jump) {
        this.canJump = true;
      }
    }
  };

//  Player.prototype.process = function() {
//    this.checkBounds();
//    this["state_" + this.state].call(this);
//  };

  Player.prototype.removeFromGame = function() {
    this.services.spriteManager.deleteSprite(this.sprite);
    this.services.spriteManager.deleteSprite(this.nameSprite);
    this.services.entitySystem.removeEntity(this);
    this.services.drawSystem.removeEntity(this);
    this.services.playerManager.removePlayer(this);
    this.services.scoreManager.deleteScoreLine(this.scoreLine);
    availableColors.push(this.color);
  };

  Player.prototype.handleDisconnect = function() {
    this.removeFromGame();
  };

  Player.prototype.handleBusyMsg = function(msg) {
    // We ignore this message
  };

  Player.prototype.handleMoveMsg = function(msg) {
    this.direction = msg.dir;
    if (this.direction) {
      this.facing = this.direction;
    }
  };

  Player.prototype.handleJumpMsg = function(msg) {
    this.jump = msg.jump;
    if (this.jump == 0) {
      this.jumpTimer = 0;
    }
  };

  Player.prototype.handleWordChoiceMsg = function(msg) {

    if ( this.services.wordManager.checkWord( msg.word ) )
    {
        this.addPoints( 1 );
        this.services.wordManager.randomizeWord();
    }
  };

  Player.prototype.handleNameMsg = function(msg) {
    if (!msg.name) {
      this.sendCmd('setName', {
        name: this.playerName
      });
    } else {
      this.setName(msg.name.replace(/[<>]/g, ''));
    }
  };

  Player.prototype.sendCmd = function(cmd, data) {
    this.netPlayer.sendCmd(cmd, data);
  };

  Player.prototype.updatePosition = function(axis, elapsedTime) {
    var axis = axis || 3;
    if (axis & 1) {
      this.position[0] += this.velocity[0] * elapsedTime;
    }
    if (axis & 3) {
      this.position[1] += this.velocity[1] * elapsedTime;
    }
  };

  Player.prototype.updateVelocity = function(axis, elapsedTime) {
    var globals = this.services.globals;
    var axis = axis || 3;
    if (axis & 1) {
      this.velocity[0] += this.acceleration[0] * elapsedTime;
      this.velocity[0] = Misc.clampPlusMinus(this.velocity[0], globals.maxVelocity[0]);
    }
    if (axis & 2) {
      this.velocity[1] += (this.acceleration[1] + globals.gravity) * elapsedTime;
      this.velocity[1] = Misc.clampPlusMinus(this.velocity[1], globals.maxVelocity[1]);
    }
  };

  Player.prototype.updatePhysics = function(axis) {
    var kOneTick = 1 / 60;
    var globals = this.services.globals;
    this.timeAccumulator += globals.elapsedTime;
    var ticks = (this.timeAccumulator / kOneTick) | 0;
    this.timeAccumulator -= ticks * kOneTick;
    this.lastPosition[0] = this.position[0];
    this.lastPosition[1] = this.position[1];
    for (var ii = 0; ii < ticks; ++ii) {
      this.updateVelocity(axis, kOneTick);
      this.updatePosition(axis, kOneTick);
    }
  };

  Player.prototype.init_idle = function() {
    this.velocity[0] = 0;
    this.velocity[1] = 0;
    this.acceleration[0] = 0;
    this.acceleration[1] = 0;
    this.animTimer = 0;
    this.anim = this.services.images.idle.colors[this.color.id];
  };

  Player.prototype.state_idle = function() {
    if (this.checkJump()) {
      return;
    } else if (this.direction) {
      this.setState('move');
      return;
    }
    var globals = this.services.globals;
    this.animTimer += globals.elapsedTime * globals.idleAnimSpeed;
    this.checkFall();
  };

  Player.prototype.init_fall = function() {
    this.animTimer = 1;
    this.anim = this.services.images.jump.colors[this.color.id];
  };

  Player.prototype.state_fall = function() {
    var globals = this.services.globals;
    this.acceleration[0] = this.direction * globals.moveAcceleration;
    this.updatePhysics();
    var landed = this.checkLand();
    this.checkWall();
    if (landed) {
      return;
    }
    if (Math.abs(this.velocity[1]) < globals.fallTopAnimVelocity) {
      this.animTimer = 2;
    } else if (this.velocity[1] >= globals.fallTopAnimVelocity) {
      this.animTimer = 3;
    }
  };

  Player.prototype.checkWall = function() {
    var levelManager = this.services.levelManager;
    var off = this.velocity[0] < 0 ? 0 : 1;
    for (var ii = 0; ii < 2; ++ii) {
      var xCheck = this.position[0] + this.checkWallOffset[off];
      var tile = levelManager.getTileInfoByPixel(xCheck, this.position[1] - this.height / 4 - this.height / 2 * ii);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.velocity[0] = 0;
        var distInTile = xCheck % level.tileWidth;
        var xoff = off ? -distInTile : level.tileWidth - distInTile;
        this.position[0] += xoff;
      }
    }
  };

  Player.prototype.checkFall = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1]);
      if (tile.collisions) {
        return false;
      }
    }
    this.setState('fall');
    return true;
  };

  Player.prototype.checkUp = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1] - this.height);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.velocity[1] = 0;
        this.position[1] = (Math.floor(this.position[1] / level.tileHeight) + 1) * level.tileHeight;
        if (!this.bonked) {
          this.bonked = true;
          this.services.audioManager.playSound('bonkhead');
          this.services.particleEffectManager.spawnBonk(this.position[0], this.position[1] - this.height);
        }
        return true;
      }
    }
    return false;
  };

  Player.prototype.checkDown = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1]);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.position[1] = Math.floor(this.position[1] / level.tileHeight) * level.tileHeight;
        this.velocity[1] = 0;
        this.services.audioManager.playSound('land');
        this.setState('move');
        return true;
      }
    }
    return false;
  };

  Player.prototype.checkLand = function() {
    if (this.velocity[1] > 0) {
      return this.checkDown();
    } else {
      return this.checkUp();
    }
  };

  Player.prototype.init_move = function() {
    this.animTimer = 0;
    this.anim = this.services.images.move.colors[this.color.id];
    this.lastDirection = this.direction;
  };

  Player.prototype.state_move = function() {
    if (this.checkJump()) {
      return;
    }

    var globals = this.services.globals;
    this.acceleration[0] = this.lastDirection * globals.moveAcceleration;
    this.animTimer += globals.moveAnimSpeed * Math.abs(this.velocity[0]) * globals.elapsedTime;
    this.updatePhysics(1);

    this.checkWall();
    this.checkFall();

    if (!this.direction) {
      this.setState('stop');
      return;
    }

    this.lastDirection = this.direction;
  };

  Player.prototype.init_stop = function() {
    this.lastDirection = this.direction;
    this.acceleration[0] = 0;
  };

  Player.prototype.state_stop = function() {
    if (this.checkJump()) {
      return;
    }

    if (this.direction) {
      this.setState('move');
      return;
    }

    var globals = this.services.globals;
    this.velocity[0] *= globals.stopFriction;
    if (Math.abs(this.velocity[0]) < globals.minStopVelocity) {
      this.setState('idle');
      return;
    }

    this.animTimer += globals.moveAnimSpeed * Math.abs(this.velocity[0]) * globals.elapsedTime;
    this.updatePhysics(1);
    this.checkWall();
    this.checkFall();
  };

  Player.prototype.init_jump = function(elaspedTime) {
    var globals = this.services.globals;
    this.jumpTimer = 0;
    this.animTimer = 0;
    this.bonked = false;
    this.anim = this.services.images.jump.colors[this.color.id];
    this.services.audioManager.playSound('jump');
  };

  Player.prototype.state_jump = function(elaspedTime) {
    var globals = this.services.globals;
    this.acceleration[0] = this.direction * globals.moveAcceleration;
    this.velocity[1] = globals.jumpVelocity;
    this.jumpTimer += globals.elapsedTime;
    this.updatePhysics();
    this.checkLand();
    this.checkWall();
    if (this.jumpTimer >= globals.jumpFirstFrameTime) {
      this.animTimer = 1;
    }
    if (this.jumpTimer >= globals.jumpDuration || !this.jump) {
      this.setState('fall');
    }
  };

  Player.prototype.draw = function() {
    var frameNumber = Math.floor(this.animTimer % this.anim.length);
    var img = this.anim[frameNumber];

    var off = {};
    this.services.levelManager.getDrawOffset(off);

    var width  = 32;
    var height = 32;

    var sprite = this.sprite;
    sprite.uniforms.u_texture = img;
    sprite.x = (off.x + this.position[0]) | 0;
    sprite.y = (off.y + height / -2 + this.position[1]) | 0;
    sprite.width = width;
    sprite.height = height;
    sprite.xScale = this.facing > 0 ? 1 : -1;

    var nameSprite = this.nameSprite;
    nameSprite.uniforms.u_texture = this.nameImage;
    nameSprite.x = (off.x + this.position[0]) | 0;
    nameSprite.y = (off.y + height / -2 + this.position[1] - 28) | 0;
    nameSprite.width = this.nameImage.img.width;
    nameSprite.height = this.nameImage.img.height;
  };

  return Player;
});

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

define([
    'hft/misc/misc',
    'hft/misc/strings',
    '../bower_components/hft-utils/dist/2d',
    '../bower_components/hft-utils/dist/imageutils',
  ], function(
    Misc,
    Strings,
    M2D,
    ImageUtils) {

  var availableColors = [];
  var nameFontOptions = {
    font: "20px sans-serif",
    yOffset: 18,
    height: 20,
    fillStyle: "black",
  };

  /**
   * Player represnt a player in the game.
   * @constructor
   */
  var Player = (function() {
    return function(services, width, height, direction, name, netPlayer) {
      this.services = services;
      this.renderer = services.renderer;
      this.netPlayer = netPlayer;
      this.velocity = [0, 0];
      this.acceleration = [0, 0];
      if (availableColors.length == 0) {
        var colors = services.colors;
        for (var ii = 0; ii < colors.length; ++ii) {
          availableColors.push(colors[ii]);
        }
      }
      var colorNdx = Math.floor(Math.random() * availableColors.length);
      this.color = availableColors[colorNdx];
window.p = this;
      netPlayer.sendCmd('setColor', this.color);
      availableColors.splice(colorNdx, 1);
      this.color.id;
      this.animTimer = 0;
      this.width = width;
      this.height = height;
      this.canJump = false;
      this.checkWallOffset = [
        -this.width / 2,
        this.width / 2 - 1,
      ];
      this.timeAccumulator = 0;

      this.scoreLine = this.services.scoreManager.createScoreLine(this, this.color);
      this.scoreLine.ctx.drawImage(
        this.services.images.idle.imgColors[this.color.id][0], 0, 0);

      netPlayer.addEventListener('disconnect', Player.prototype.handleDisconnect.bind(this));
      netPlayer.addEventListener('setName', Player.prototype.handleNameMsg.bind(this));
      netPlayer.addEventListener('busy', Player.prototype.handleBusyMsg.bind(this));
      netPlayer.addEventListener('word choice', Player.prototype.handleWordChoiceMsg.bind(this));

      this.setName(name);
      this.direction = 0;         // direction player is pushing (-1, 0, 1)
      this.facing = direction;    // direction player is facing (-1, 1)
      this.score = 0;
      this.addPoints(0);

      this.setState('idle');
      this.reset();
      this.checkBounds();
    };
  }());

  Player.prototype.setName = function(name) {
    if (name != this.playerName) {
      this.playerName = name;
      this.scoreLine.setName(":" + name);
    }
  };

  Player.prototype.reset = function() {
    var levelManager = this.services.levelManager;
    var level = levelManager.getLevel();
    var position = levelManager.getRandomOpenPosition();
    this.position = [position.x, position.y];
    this.lastPosition = [this.position[0], this.position[1]];
  };

  Player.prototype.addPoints = function(points) {
    this.score += points;
    this.scoreLine.setMsg(Strings.padLeft(this.score, 3, "0"));
  };

  Player.prototype.setState = function(state) {
    this.state = state;
    var init = this["init_" + state];
    if (init) {
      init.call(this);
    }
    this.process = this["state_" + state];
  };

  Player.prototype.checkBounds = function() {
    var levelManager = this.services.levelManager;
    var level = levelManager.getLevel();

    if (this.position[1] > level.width * level.tileHeight) {
      debugger;
    }
  };

  Player.prototype.checkJump = function() {
    if (this.canJump) {
      if (this.jump) {
        this.canJump = false;
        this.setState('jump');
      }
    } else {
      if (!this.jump) {
        this.canJump = true;
      }
    }
  };

//  Player.prototype.process = function() {
//    this.checkBounds();
//    this["state_" + this.state].call(this);
//  };

  Player.prototype.removeFromGame = function() {
    this.services.playerManager.removePlayer(this);
    this.services.scoreManager.deleteScoreLine(this.scoreLine);
    availableColors.push(this.color);
  };

  Player.prototype.handleDisconnect = function() {
    this.removeFromGame();
  };

  Player.prototype.handleBusyMsg = function(msg) {
    // We ignore this message
  };

  Player.prototype.handleWordChoiceMsg = function(msg) {

    if ( this.services.wordManager.checkWord( msg.word ) )
    {
        this.addPoints( 1 );
        this.services.wordManager.randomizeWord();
    }
  };

  Player.prototype.handleNameMsg = function(msg) {
    if (!msg.name) {
      this.sendCmd('setName', {
        name: this.playerName
      });
    } else {
      this.setName(msg.name.replace(/[<>]/g, ''));
    }
  };

  Player.prototype.sendCmd = function(cmd, data) {
    this.netPlayer.sendCmd(cmd, data);
  };

  Player.prototype.updatePosition = function(axis, elapsedTime) {
    var axis = axis || 3;
    if (axis & 1) {
      this.position[0] += this.velocity[0] * elapsedTime;
    }
    if (axis & 3) {
      this.position[1] += this.velocity[1] * elapsedTime;
    }
  };

  Player.prototype.updateVelocity = function(axis, elapsedTime) {
    var globals = this.services.globals;
    var axis = axis || 3;
    if (axis & 1) {
      this.velocity[0] += this.acceleration[0] * elapsedTime;
      this.velocity[0] = Misc.clampPlusMinus(this.velocity[0], globals.maxVelocity[0]);
    }
    if (axis & 2) {
      this.velocity[1] += (this.acceleration[1] + globals.gravity) * elapsedTime;
      this.velocity[1] = Misc.clampPlusMinus(this.velocity[1], globals.maxVelocity[1]);
    }
  };

  Player.prototype.updatePhysics = function(axis) {
    var kOneTick = 1 / 60;
    var globals = this.services.globals;
    this.timeAccumulator += globals.elapsedTime;
    var ticks = (this.timeAccumulator / kOneTick) | 0;
    this.timeAccumulator -= ticks * kOneTick;
    this.lastPosition[0] = this.position[0];
    this.lastPosition[1] = this.position[1];
    for (var ii = 0; ii < ticks; ++ii) {
      this.updateVelocity(axis, kOneTick);
      this.updatePosition(axis, kOneTick);
    }
  };

  Player.prototype.init_idle = function() {
    this.velocity[0] = 0;
    this.velocity[1] = 0;
    this.acceleration[0] = 0;
    this.acceleration[1] = 0;
    this.animTimer = 0;
    this.anim = this.services.images.idle.colors[this.color.id];
  };

  Player.prototype.state_idle = function() {
    if (this.checkJump()) {
      return;
    } else if (this.direction) {
      this.setState('move');
      return;
    }
    var globals = this.services.globals;
    this.animTimer += globals.elapsedTime * globals.idleAnimSpeed;
    this.checkFall();
  };

  Player.prototype.init_fall = function() {
    this.animTimer = 1;
    this.anim = this.services.images.jump.colors[this.color.id];
  };

  Player.prototype.state_fall = function() {
    var globals = this.services.globals;
    this.acceleration[0] = this.direction * globals.moveAcceleration;
    this.updatePhysics();
    var landed = this.checkLand();
    this.checkWall();
    if (landed) {
      return;
    }
    if (Math.abs(this.velocity[1]) < globals.fallTopAnimVelocity) {
      this.animTimer = 2;
    } else if (this.velocity[1] >= globals.fallTopAnimVelocity) {
      this.animTimer = 3;
    }
  };

  Player.prototype.checkWall = function() {
    var levelManager = this.services.levelManager;
    var off = this.velocity[0] < 0 ? 0 : 1;
    for (var ii = 0; ii < 2; ++ii) {
      var xCheck = this.position[0] + this.checkWallOffset[off];
      var tile = levelManager.getTileInfoByPixel(xCheck, this.position[1] - this.height / 4 - this.height / 2 * ii);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.velocity[0] = 0;
        var distInTile = xCheck % level.tileWidth;
        var xoff = off ? -distInTile : level.tileWidth - distInTile;
        this.position[0] += xoff;
      }
    }
  };

  Player.prototype.checkFall = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1]);
      if (tile.collisions) {
        return false;
      }
    }
    this.setState('fall');
    return true;
  };

  Player.prototype.checkUp = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1] - this.height);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.velocity[1] = 0;
        this.position[1] = (Math.floor(this.position[1] / level.tileHeight) + 1) * level.tileHeight;
        if (!this.bonked) {
          this.bonked = true;
          this.services.audioManager.playSound('bonkhead');
          this.services.particleEffectManager.spawnBonk(this.position[0], this.position[1] - this.height);
        }
        return true;
      }
    }
    return false;
  };

  Player.prototype.checkDown = function() {
    var levelManager = this.services.levelManager;
    for (var ii = 0; ii < 2; ++ii) {
      var tile = levelManager.getTileInfoByPixel(this.position[0] - this.width / 4 + this.width / 2 * ii, this.position[1]);
      if (tile.collisions) {
        var level = levelManager.getLevel();
        this.position[1] = Math.floor(this.position[1] / level.tileHeight) * level.tileHeight;
        this.velocity[1] = 0;
        this.services.audioManager.playSound('land');
        this.setState('move');
        return true;
      }
    }
    return false;
  };

  Player.prototype.checkLand = function() {
    if (this.velocity[1] > 0) {
      return this.checkDown();
    } else {
      return this.checkUp();
    }
  };

  Player.prototype.init_move = function() {
    this.animTimer = 0;
    this.anim = this.services.images.move.colors[this.color.id];
    this.lastDirection = this.direction;
  };

  Player.prototype.state_move = function() {
    if (this.checkJump()) {
      return;
    }

    var globals = this.services.globals;
    this.acceleration[0] = this.lastDirection * globals.moveAcceleration;
    this.animTimer += globals.moveAnimSpeed * Math.abs(this.velocity[0]) * globals.elapsedTime;
    this.updatePhysics(1);

    this.checkWall();
    this.checkFall();

    if (!this.direction) {
      this.setState('stop');
      return;
    }

    this.lastDirection = this.direction;
  };

  Player.prototype.init_stop = function() {
    this.lastDirection = this.direction;
    this.acceleration[0] = 0;
  };

  Player.prototype.state_stop = function() {
    if (this.checkJump()) {
      return;
    }

    if (this.direction) {
      this.setState('move');
      return;
    }

    var globals = this.services.globals;
    this.velocity[0] *= globals.stopFriction;
    if (Math.abs(this.velocity[0]) < globals.minStopVelocity) {
      this.setState('idle');
      return;
    }

    this.animTimer += globals.moveAnimSpeed * Math.abs(this.velocity[0]) * globals.elapsedTime;
    this.updatePhysics(1);
    this.checkWall();
    this.checkFall();
  };

  Player.prototype.init_jump = function(elaspedTime) {
    var globals = this.services.globals;
    this.jumpTimer = 0;
    this.animTimer = 0;
    this.bonked = false;
    this.anim = this.services.images.jump.colors[this.color.id];
    this.services.audioManager.playSound('jump');
  };

  Player.prototype.state_jump = function(elaspedTime) {
    var globals = this.services.globals;
    this.acceleration[0] = this.direction * globals.moveAcceleration;
    this.velocity[1] = globals.jumpVelocity;
    this.jumpTimer += globals.elapsedTime;
    this.updatePhysics();
    this.checkLand();
    this.checkWall();
    if (this.jumpTimer >= globals.jumpFirstFrameTime) {
      this.animTimer = 1;
    }
    if (this.jumpTimer >= globals.jumpDuration || !this.jump) {
      this.setState('fall');
    }
  };

  return Player;
});

<|endoftext|>


<commit_before>function player_Init() {
    Player.init();
}

var Player = {
	_player: null,
	_playerReady: false,
	_hiddenPlaylist: ['',
		'','','','','','','','','','',
		'','','','','','','sIakSu5VGF0', 'fWucPckXbIw','ypWr6pwoZmI','Tg4u7ko333U',
		'lcOxhH8N3Bo','dJYAenuVnQw','w789CzQdMl0','N2bCc0EGP6U','P0aXY2pM2sA','-kHzZZvsdOE','kz6vq-409Vg','iSF2YHqHJc4','6f8FCHzRcOs','z2Am3aLwu1E',
		'D5fRVm3k1aY','--_KyuZMsnA','6zcrgSB5pkU','sTsVJ1PsnMs','vF74D3kbbTI','6_W_xLWtNa0','_Y-suQWFOfg','xNidwV6OZ3w','wp43OdtAAkM','2aljlKYesT4',
		'P9mwELXPGbA','loWXMtjUZWM','PJQVlVHsFF8','cBFANonCPpk','0qGTjIcVDAU','lp_PIjc2ga4','','','','',
		'', ''], // One for each week :)
	_playbackQuality: ['small', 'medium', 'large', 'hd720', 'hd1080', 'highres'],
	_isFullscreen: false,
	_lastVideoId: null,
	_currentVideoId: null,
	_loadingNewVideo: null, // avoid buffer hang at start
	_playOrderIndex: 0,
	_playOrderList: [],
	_queue: [],

    init: function() {

    },

    getCurrentVideoId: function() {
        return Player._currentVideoId;
    },

	play: function(video) {
        var videoId, title;
        if (video) {
            if (typeof video === typeof 'string') {
                videoId = video;
            } else {
                videoId = video.videoId;
                title = video.title;
            }
        }

        if (!youTubeApiReady) {
            setTimeout(function() {
                Player.play(video);
            }, 1000);
            return;
        }

        if (Player._lastVideoId !== Player._currentVideoId) {
            FatBar.clear();
        }

        $('#bottom .info, #bottom .share-wrapper').show();

		if (videoId !== undefined) {
            history.pushState(null, null, '/videos/' + videoId);
            Player._currentVideoId = videoId;
			var quality = new Settings().quality || 'hd720';
			Player._loadingNewVideo = true;

			// Make sure currentVideoId is set before assert
			if (Player.assertPlayerLoaded()) {
				try {
					Player._player.loadVideoById(videoId, 0, quality);
				} catch (ex) {
					console.log(ex);
					Notification.say('An error has occurred with the player. Please reload the page.');
				}
			}

			if (title !== undefined) {
				Player.setTitle(title);
			} else {
				Player.loadTitle(videoId);
			}
			// avoid buffer hang at start
		} else {
			Player.assertPlayerLoaded();
		}

        if (Player._player.playVideo) {
            Player._player.playVideo();
        }
	},

	pause: function() {
		if (!Player._playerReady) {
            return;
        }
		Player.assertPlayerLoaded();

		Player._player.pauseVideo();
	},

	playPause: function() {
		if (!Player._playerReady) {
            return;
        }
		Player.assertPlayerLoaded();

		if (Player._player.getPlayerState() === 1) {
			Player.pause();
		} else {
			Player.play();
		}
	},

	prev: function() {
		Player.assertPlayerLoaded();

		if (Player._player.getCurrentTime() > 3) {
			Player._player.seekTo(0);
		} else {
			var elem = null;
			if (Player._playOrderList.length > 0) {
				if (Player._playOrderIndex-1 >= 0) {
					elem = $(Player._playOrderList[Player._playOrderIndex -= 1]);
				} else {
					return;
				}
			} else {
				elem = $('#results-container li.playing').prev();
			}
			if (elem.hasClass('alternative')) {
				elem = elem.parent().parent().prev();
			}
			if (elem.length > 0) {
				elem.play();
            }
		}
	},

	next: function() {
		Player.assertPlayerLoaded();

		var elem = null;
		// Queue
		if (Player._queue.length > 0) {
			elem = Player._queue.shift();
			if (elem.originalElem.parent().length > 0) {
				elem = elem.originalElem;
				elem.play();
			} else {
				Player.play(elem.data('model'));
			}
			return;
		}
		// Playlist
		if (Player._playOrderList.length > 0) {
			if (Player._playOrderIndex+1 <= Player._playOrderList.length) {
				elem = $(Player._playOrderList[Player._playOrderIndex += 1]);
			} else if (Player._playOrderIndex+1 > Player._playOrderList.length) {
				Player._playOrderList = [];
				Player._playOrderIndex = 0;
				return;
			}
		} else {
			elem = $('#right .playing').next();
		}
		if (elem.hasClass('alternative')) {
			elem = elem.parent().parent().next();
		} else if (elem.hasClass('loadMore')) {
			// load more and continue playing
			elem.addClass('loading');
			Search.searchVideos('', true, true);
		}
		if (elem.length > 0) {
			elem.data('model').play();
		}
	},

	addSiblingsToPlayorder: function(startElem, shuffle) {
		if (startElem === undefined) {
			return;
        }
		Player._playOrderList = [];
		Player._playOrderIndex = 0;
		if (shuffle) {
			// add all siblings to the list
			$(startElem).siblings().each(function(index, item) {
				Player._playOrderList.push(item);
			});
			$.shuffle(Player._playOrderList);
			// find the start elem and move it to the top of the list
			$.each(Player._playOrderList, function(index, item) {
				if (item === startElem) {
					Player._playOrderList.splice(index, 1);
					Player._playOrderList.unshift(startElem);
				}
			});
		} else {
			var elem = startElem;
			while(elem.length > 0) {
				Player._playOrderList.push(elem);
				elem = $(elem).next();
			}
		}
	},

	addToPlayOrder: function(elem) {
		Player._queue.push({
			videoId: elem.data('videoId'),
			title: elem.find('.title').text(),
			originalElem: elem
		});
	},

	setTitle: function(title) {
		var videoId = Player.getCurrentVideoId();
        document.title = "Youtify - " + title;
		$('#bottom .info .title').text(title).attr('title', title);
        if (title && title.length > 0) {
            Notification.say(title);
        }
	},

    _startedPlayingVideoSuccessfully: function() {
        var title = $('#bottom .info .title').text();
        var video = new Video(Player._currentVideoId, title);
        EventSystem.callEventHandlers('video_started_playing_successfully', video);
        Notification.say(title);
    },

	onPlayerStateChange: function(event) {
		//unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)

		Timeline.stop();

		if (event.data !== 5) {
			if ($('body').hasClass('playing')) {
				$('body').removeClass('playing');
            }
			$('body').addClass('paused');
		}

		switch (event.data) {
			case -1:
				// avoid buffer hang at start
				if (Player._loadingNewVideo){
					Player._loadingNewVideo = null;
					Player.play();
				}
				break;
			case 0: // ended
				Player.next();
				break;
			case 1:
				// avoid buffer hang at start
				if (Player._loadingNewVideo) {
					Player._loadingNewVideo = null;
                }
				if ($('body').hasClass('paused')) {
					$('body').removeClass('paused');
                }
				$('body').addClass('playing');
				Timeline.start();
                if (Player._lastVideoId !== Player._currentVideoId) {
                    Player._startedPlayingVideoSuccessfully();
                    Player._lastVideoId = Player._currentVideoId;
                }
				break;
			case 2:
				break;
			case 3:
				// Avoid buffer hang at end (rare)
				var pos = Player._player.getCurrentTime();
				var len = Player._player.getDuration();
				if (pos > len-2.0 && len > 0) {
					Player.next();
                }
				break;
			case 5:
				break;
		}
	},

	onError: function(event) {
		var messages = {
            2: 'Sorry, the video requested cannot be played. Invalid video ID.',
            //100: 'The requested video was not found. The video is removed or marked as private.',
            //101: 'The 101 error code is broadcast when the video requested does not allow playback in the embedded players.',
            //150: 'The 150 error code is broadcast when the video requested does not allow playback in the embedded players.'
            100: 'The rights holder has decided not to share this video on Youtify',
            150: 'The rights holder has decided not to share this video on Youtify'
        };
		var elem = $('#right .playing');
        // No playitem found
        if (elem.length === 0) {
            Notification.say(messages[event.data]);
            return;
        }
		if (elem.hasClass('alternative')) {
			if (elem.next().length > 0) {
				elem.next().play();
			} else {
				Player.next();
			}
			elem.remove();
			return;
		}
		if (elem.hasClass('fake') && elem.find('ul').length) {
			elem.find('li:first-child').play();
			return;
		}
		elem.addClass('disabled');
		Search.findAndPlayAlternative(elem);
		Notification.say(messages[event.data]);
	},

	playPrevAlternative: function() {
		var elem = $('.alternatives .playing');
		if (elem && elem.prev()) {
			elem.prev().play();
        }
	},

	playNextAlternative: function() {
		var elem = $('.alternatives .playing');
		if (elem && elem.next()) {
			elem.next().play();
        }
	},

	seekForward: function(step) {
		Player.assertPlayerLoaded();

		var pos = Player._player.getCurrentTime();
		var len = Player._player.getDuration();
		if (step !== undefined) {
			pos += step;
		} else {
			pos += 10;
        }
		if (pos > len) {
			return;
        }
		Player._player.seekTo(pos, true);
	},

	seekBackward: function(step) {
		Player.assertPlayerLoaded();

		var pos = Player._player.getCurrentTime();
		if (step !== undefined) {
			pos -= step;
		} else {
			pos -= 10;
        }
		if (pos < 0) {
			pos = 0;
        }
		Player._player.seekTo(pos, true);
	},

	toggleFullscreen: function() {
		if (Player._isFullscreen) {
			Player.stopFullscreen();
		} else {
			Player.startFullscreen();
		}
	},

	startFullscreen: function() {
		if (!Player._playerReady) {
			return;
		}
        var $youtubePlayerElem = $('#left .players .youtube');
		// Must set style, not class (and not position).
		Player._isFullscreen = true;
		$($youtubePlayerElem).css('left',0);
		$($youtubePlayerElem).css('top',0);
		var width = $(window).width();
		var height = $(window).height() -45;
		$($youtubePlayerElem).width(width);
		$($youtubePlayerElem).height(height);
		Player._player.setSize(width, height);

		$('#bottom .fullscreen').addClass('minimize'); // TODO create elem in index.html
	},

	stopFullscreen: function() {
		Player._isFullscreen = false;
        var $youtubePlayerElem = $('#left .players .youtube');
		var width = 230;
		var height = 230;
		$($youtubePlayerElem).width(width);
		$($youtubePlayerElem).height(height);
		Player._player.setSize(width, height);

		$(window).resize();
		$('#bottom .fullscreen').removeClass('minimize'); // TODO create elem in index.html
	},

	volumeUp: function(step) {
		if (!Player._playerReady) {
			return;
		}

		var volume = Player._player.getVolume();
		if (step !== undefined) {
			volume += step;
		} else {
			volume += 5;
        }
		if (volume > 100) {
			volume = 100;
        }
		Player._player.setVolume(volume);
	},

	volumeDown: function(step) {
		if (!Player._playerReady) {
			return;
		}

		var volume = Player._player.getVolume();
		if (step !== undefined) {
			volume -= step;
		} else {
			volume -= 5;
        }
		if (volume < 0) {
			volume = 0;
        }
		Player._player.setVolume(volume);
	},

	setVolume: function(volume) {
		if (!Player._playerReady) {
			return;
		}

		if (volume === undefined || volume > 100) {
			volume = 100;
        }
		if (volume < 0) {
			volume = 0;
        }
		Player._player.setVolume(volume);
	},

	loadTitle: function(videoId) {
		var url = "http://gdata.youtube.com/feeds/api/videos?callback=?";
		var params = {
			'alt': 'json-in-script',
			'max-results': 1,
			'prettyprint': true,
			'fields': 'entry(title)',
			'v': 2,
			'q': videoId
		};
		Player.setTitle('');
		$.getJSON(url, params, function(data) {

			if (data.feed.entry) {
                var title;
                if (data.feed.entry[0].title.$t) {
                    title = data.feed.entry[0].title.$t;
                } else {
                    return;
                }
                Player.setTitle(title);
            }
		});
	},

	loadIFramePlayer: function() {
        $youtubePlayerElem = $('#left .players .youtube');
        $youtubePlayerElem.html(''); // remove old iframe

		var videoId = Player.getCurrentVideoId() || '';
		var origin = document.location.origin || document.location.protocol + '//' + document.location.host;
		Player._player = new YT.Player('youtube', {
          height: '230',
          width: '230',
		  videoId: videoId,
		  enablejsapi: 1,
		  modestbranding: 1,
		  origin: origin,
		  playerVars: { 'autoplay': 1, 'controls': 0 },
          events: {
            'onReady': Player.onIFramePlayerReady,
            'onStateChange': Player.onPlayerStateChange,
			'onError': Player.onError
          }
        });
	},

	onIFramePlayerReady: function(event) {
		Player._playerReady = true;
	},

	assertPlayerLoaded: function() {
		if (Player._player === undefined || Player._player === null || Player._player.getPlayerState === undefined) {
			Player._playerReady = false;

			console.log("Reloading player");
			Player.loadIFramePlayer();
		}
		return Player._playerReady;
	}
};
<commit_msg>Changed line endings in player.js<commit_after>function player_Init() {
    Player.init();
}

var Player = {
	_player: null,
	_playerReady: false,
	_hiddenPlaylist: ['',
		'','','','','','','','','','',
		'','','','','','','sIakSu5VGF0', 'fWucPckXbIw','ypWr6pwoZmI','Tg4u7ko333U',
		'lcOxhH8N3Bo','dJYAenuVnQw','w789CzQdMl0','N2bCc0EGP6U','P0aXY2pM2sA','-kHzZZvsdOE','kz6vq-409Vg','iSF2YHqHJc4','6f8FCHzRcOs','z2Am3aLwu1E',
		'D5fRVm3k1aY','--_KyuZMsnA','6zcrgSB5pkU','sTsVJ1PsnMs','vF74D3kbbTI','6_W_xLWtNa0','_Y-suQWFOfg','xNidwV6OZ3w','wp43OdtAAkM','2aljlKYesT4',
		'P9mwELXPGbA','loWXMtjUZWM','PJQVlVHsFF8','cBFANonCPpk','0qGTjIcVDAU','lp_PIjc2ga4','','','','',
		'', ''], // One for each week :)
	_playbackQuality: ['small', 'medium', 'large', 'hd720', 'hd1080', 'highres'],
	_isFullscreen: false,
	_lastVideoId: null,
	_currentVideoId: null,
	_loadingNewVideo: null, // avoid buffer hang at start
	_playOrderIndex: 0,
	_playOrderList: [],
	_queue: [],

    init: function() {

    },

    getCurrentVideoId: function() {
        return Player._currentVideoId;
    },

	play: function(video) {
        var videoId, title;
        if (video) {
            if (typeof video === typeof 'string') {
                videoId = video;
            } else {
                videoId = video.videoId;
                title = video.title;
            }
        }

        if (!youTubeApiReady) {
            setTimeout(function() {
                Player.play(video);
            }, 1000);
            return;
        }

        if (Player._lastVideoId !== Player._currentVideoId) {
            FatBar.clear();
        }

        $('#bottom .info, #bottom .share-wrapper').show();

		if (videoId !== undefined) {
            history.pushState(null, null, '/videos/' + videoId);
            Player._currentVideoId = videoId;
			var quality = new Settings().quality || 'hd720';
			Player._loadingNewVideo = true;

			// Make sure currentVideoId is set before assert
			if (Player.assertPlayerLoaded()) {
				try {
					Player._player.loadVideoById(videoId, 0, quality);
				} catch (ex) {
					console.log(ex);
					Notification.say('An error has occurred with the player. Please reload the page.');
				}
			}

			if (title !== undefined) {
				Player.setTitle(title);
			} else {
				Player.loadTitle(videoId);
			}
			// avoid buffer hang at start
		} else {
			Player.assertPlayerLoaded();
		}

        if (Player._player.playVideo) {
            Player._player.playVideo();
        }
	},

	pause: function() {
		if (!Player._playerReady) {
            return;
        }
		Player.assertPlayerLoaded();

		Player._player.pauseVideo();
	},

	playPause: function() {
		if (!Player._playerReady) {
            return;
        }
		Player.assertPlayerLoaded();

		if (Player._player.getPlayerState() === 1) {
			Player.pause();
		} else {
			Player.play();
		}
	},

	prev: function() {
		Player.assertPlayerLoaded();

		if (Player._player.getCurrentTime() > 3) {
			Player._player.seekTo(0);
		} else {
			var elem = null;
			if (Player._playOrderList.length > 0) {
				if (Player._playOrderIndex-1 >= 0) {
					elem = $(Player._playOrderList[Player._playOrderIndex -= 1]);
				} else {
					return;
				}
			} else {
				elem = $('#results-container li.playing').prev();
			}
			if (elem.hasClass('alternative')) {
				elem = elem.parent().parent().prev();
			}
			if (elem.length > 0) {
				elem.play();
            }
		}
	},

	next: function() {
		Player.assertPlayerLoaded();

		var elem = null;
		// Queue
		if (Player._queue.length > 0) {
			elem = Player._queue.shift();
			if (elem.originalElem.parent().length > 0) {
				elem = elem.originalElem;
				elem.play();
			} else {
				Player.play(elem.data('model'));
			}
			return;
		}
		// Playlist
		if (Player._playOrderList.length > 0) {
			if (Player._playOrderIndex+1 <= Player._playOrderList.length) {
				elem = $(Player._playOrderList[Player._playOrderIndex += 1]);
			} else if (Player._playOrderIndex+1 > Player._playOrderList.length) {
				Player._playOrderList = [];
				Player._playOrderIndex = 0;
				return;
			}
		} else {
			elem = $('#right .playing').next();
		}
		if (elem.hasClass('alternative')) {
			elem = elem.parent().parent().next();
		} else if (elem.hasClass('loadMore')) {
			// load more and continue playing
			elem.addClass('loading');
			Search.searchVideos('', true, true);
		}
		if (elem.length > 0) {
			elem.data('model').play();
		}
	},

	addSiblingsToPlayorder: function(startElem, shuffle) {
		if (startElem === undefined) {
			return;
        }
		Player._playOrderList = [];
		Player._playOrderIndex = 0;
		if (shuffle) {
			// add all siblings to the list
			$(startElem).siblings().each(function(index, item) {
				Player._playOrderList.push(item);
			});
			$.shuffle(Player._playOrderList);
			// find the start elem and move it to the top of the list
			$.each(Player._playOrderList, function(index, item) {
				if (item === startElem) {
					Player._playOrderList.splice(index, 1);
					Player._playOrderList.unshift(startElem);
				}
			});
		} else {
			var elem = startElem;
			while(elem.length > 0) {
				Player._playOrderList.push(elem);
				elem = $(elem).next();
			}
		}
	},

	addToPlayOrder: function(elem) {
		Player._queue.push({
			videoId: elem.data('videoId'),
			title: elem.find('.title').text(),
			originalElem: elem
		});
	},

	setTitle: function(title) {
		var videoId = Player.getCurrentVideoId();
        document.title = "Youtify - " + title;
		$('#bottom .info .title').text(title).attr('title', title);
        if (title && title.length > 0) {
            Notification.say(title);
        }
	},

    _startedPlayingVideoSuccessfully: function() {
        var title = $('#bottom .info .title').text();
        var video = new Video(Player._currentVideoId, title);
        EventSystem.callEventHandlers('video_started_playing_successfully', video);
        Notification.say(title);
    },

	onPlayerStateChange: function(event) {
		//unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)

		Timeline.stop();

		if (event.data !== 5) {
			if ($('body').hasClass('playing')) {
				$('body').removeClass('playing');
            }
			$('body').addClass('paused');
		}

		switch (event.data) {
			case -1:
				// avoid buffer hang at start
				if (Player._loadingNewVideo){
					Player._loadingNewVideo = null;
					Player.play();
				}
				break;
			case 0: // ended
				Player.next();
				break;
			case 1:
				// avoid buffer hang at start
				if (Player._loadingNewVideo) {
					Player._loadingNewVideo = null;
                }
				if ($('body').hasClass('paused')) {
					$('body').removeClass('paused');
                }
				$('body').addClass('playing');
				Timeline.start();
                if (Player._lastVideoId !== Player._currentVideoId) {
                    Player._startedPlayingVideoSuccessfully();
                    Player._lastVideoId = Player._currentVideoId;
                }
				break;
			case 2:
				break;
			case 3:
				// Avoid buffer hang at end (rare)
				var pos = Player._player.getCurrentTime();
				var len = Player._player.getDuration();
				if (pos > len-2.0 && len > 0) {
					Player.next();
                }
				break;
			case 5:
				break;
		}
	},

	onError: function(event) {
		var messages = {
            2: 'Sorry, the video requested cannot be played. Invalid video ID.',
            //100: 'The requested video was not found. The video is removed or marked as private.',
            //101: 'The 101 error code is broadcast when the video requested does not allow playback in the embedded players.',
            //150: 'The 150 error code is broadcast when the video requested does not allow playback in the embedded players.'
            100: 'The rights holder has decided not to share this video on Youtify',
            150: 'The rights holder has decided not to share this video on Youtify'
        };
		var elem = $('#right .playing');
        // No playitem found
        if (elem.length === 0) {
            Notification.say(messages[event.data]);
            return;
        }
		if (elem.hasClass('alternative')) {
			if (elem.next().length > 0) {
				elem.next().play();
			} else {
				Player.next();
			}
			elem.remove();
			return;
		}
		if (elem.hasClass('fake') && elem.find('ul').length) {
			elem.find('li:first-child').play();
			return;
		}
		elem.addClass('disabled');
		Search.findAndPlayAlternative(elem);
		Notification.say(messages[event.data]);
	},

	playPrevAlternative: function() {
		var elem = $('.alternatives .playing');
		if (elem && elem.prev()) {
			elem.prev().play();
        }
	},

	playNextAlternative: function() {
		var elem = $('.alternatives .playing');
		if (elem && elem.next()) {
			elem.next().play();
        }
	},

	seekForward: function(step) {
		Player.assertPlayerLoaded();

		var pos = Player._player.getCurrentTime();
		var len = Player._player.getDuration();
		if (step !== undefined) {
			pos += step;
		} else {
			pos += 10;
        }
		if (pos > len) {
			return;
        }
		Player._player.seekTo(pos, true);
	},

	seekBackward: function(step) {
		Player.assertPlayerLoaded();

		var pos = Player._player.getCurrentTime();
		if (step !== undefined) {
			pos -= step;
		} else {
			pos -= 10;
        }
		if (pos < 0) {
			pos = 0;
        }
		Player._player.seekTo(pos, true);
	},

	toggleFullscreen: function() {
		if (Player._isFullscreen) {
			Player.stopFullscreen();
		} else {
			Player.startFullscreen();
		}
	},

	startFullscreen: function() {
		if (!Player._playerReady) {
			return;
		}
        var $youtubePlayerElem = $('#left .players .youtube');
		// Must set style, not class (and not position).
		Player._isFullscreen = true;
		$($youtubePlayerElem).css('left',0);
		$($youtubePlayerElem).css('top',0);
		var width = $(window).width();
		var height = $(window).height() -45;
		$($youtubePlayerElem).width(width);
		$($youtubePlayerElem).height(height);
		Player._player.setSize(width, height);

		$('#bottom .fullscreen').addClass('minimize'); // TODO create elem in index.html
	},

	stopFullscreen: function() {
		Player._isFullscreen = false;
        var $youtubePlayerElem = $('#left .players .youtube');
		var width = 230;
		var height = 230;
		$($youtubePlayerElem).width(width);
		$($youtubePlayerElem).height(height);
		Player._player.setSize(width, height);

		$(window).resize();
		$('#bottom .fullscreen').removeClass('minimize'); // TODO create elem in index.html
	},

	volumeUp: function(step) {
		if (!Player._playerReady) {
			return;
		}

		var volume = Player._player.getVolume();
		if (step !== undefined) {
			volume += step;
		} else {
			volume += 5;
        }
		if (volume > 100) {
			volume = 100;
        }
		Player._player.setVolume(volume);
	},

	volumeDown: function(step) {
		if (!Player._playerReady) {
			return;
		}

		var volume = Player._player.getVolume();
		if (step !== undefined) {
			volume -= step;
		} else {
			volume -= 5;
        }
		if (volume < 0) {
			volume = 0;
        }
		Player._player.setVolume(volume);
	},

	setVolume: function(volume) {
		if (!Player._playerReady) {
			return;
		}

		if (volume === undefined || volume > 100) {
			volume = 100;
        }
		if (volume < 0) {
			volume = 0;
        }
		Player._player.setVolume(volume);
	},

	loadTitle: function(videoId) {
		var url = "http://gdata.youtube.com/feeds/api/videos?callback=?";
		var params = {
			'alt': 'json-in-script',
			'max-results': 1,
			'prettyprint': true,
			'fields': 'entry(title)',
			'v': 2,
			'q': videoId
		};
		Player.setTitle('');
		$.getJSON(url, params, function(data) {

			if (data.feed.entry) {
                var title;
                if (data.feed.entry[0].title.$t) {
                    title = data.feed.entry[0].title.$t;
                } else {
                    return;
                }
                Player.setTitle(title);
            }
		});
	},

	loadIFramePlayer: function() {
        $youtubePlayerElem = $('#left .players .youtube');
        $youtubePlayerElem.html(''); // remove old iframe

		var videoId = Player.getCurrentVideoId() || '';
		var origin = document.location.origin || document.location.protocol + '//' + document.location.host;
		Player._player = new YT.Player('youtube', {
          height: '230',
          width: '230',
		  videoId: videoId,
		  enablejsapi: 1,
		  modestbranding: 1,
		  origin: origin,
		  playerVars: { 'autoplay': 1, 'controls': 0 },
          events: {
            'onReady': Player.onIFramePlayerReady,
            'onStateChange': Player.onPlayerStateChange,
			'onError': Player.onError
          }
        });
	},

	onIFramePlayerReady: function(event) {
		Player._playerReady = true;
	},

	assertPlayerLoaded: function() {
		if (Player._player === undefined || Player._player === null || Player._player.getPlayerState === undefined) {
			Player._playerReady = false;

			console.log("Reloading player");
			Player.loadIFramePlayer();
		}
		return Player._playerReady;
	}
};
<|endoftext|>


<commit_before>window.shower = (function(window, document, undefined) {
	var shower = {},
		url = window.location,
		body = document.body,
		slides = document.querySelectorAll('.slide'),
		progress = document.querySelector('div.progress div'),
		slideList = [],
		timer,
		l = slides.length, i;

	for (i = 0; i < l; i++) {
		// Slide ID's are optional. In case of missing ID we set it to the
		// slide number
		if (!slides[i].id) {
			slides[i].id = i + 1;
		}

		slideList.push({
			id: slides[i].id,
			hasInnerNavigation: null !== slides[i].querySelector('.next'),
			hasTiming: (slides[i].dataset.timing && slides[i].dataset.timing.indexOf(':') !== -1)
		});
	}

	shower._getTransform = function() {
		var denominator = Math.max(
			body.clientWidth / window.innerWidth,
			body.clientHeight / window.innerHeight
		);

		return 'scale(' + (1 / denominator) + ')';
	};

	shower._applyTransform = function(transform) {
		body.style.WebkitTransform = transform;
		body.style.MozTransform = transform;
		body.style.msTransform = transform;
		body.style.OTransform = transform;
		body.style.transform = transform;
	};

	shower.next = function () {
		var currentSlideNumber = shower.getCurrentSlideNumber();

		// Only go to next slide if current slide have no inner
		// navigation or inner navigation is fully shown
		// NOTE: But first of all check if there is no current slide
		if (
			-1 === currentSlideNumber ||
			!slideList[currentSlideNumber].hasInnerNavigation ||
			-1 === increaseInnerNavigation(currentSlideNumber)
		) {
			currentSlideNumber++;
			shower.go(currentSlideNumber);
		}
	};

	shower.previous = function () {
		shower.go(shower.getCurrentSlideNumber() - 1);
	};

	shower.first = function() {
		shower.go(0);
	};

	shower.last = function() {
		shower.go(slideList.length - 1);
	};

	shower.enterSlideMode = function() {
		body.classList.remove('list');
		body.classList.add('full');
		shower._applyTransform(shower._getTransform());
	};

	shower.enterListMode = function() {
		body.classList.remove('full');
		body.classList.add('list');
		shower._applyTransform('none');
	};

	shower.getCurrentSlideNumber = function() {
		var i = 0,
			l = slideList.length,
			currentSlideId = url.hash.substr(1);

		for (; i < l; ++i) {
			if (currentSlideId === slideList[i].id) {
				return i;
			}
		}

		return -1;
	};

	shower.scrollToSlide = function(slideNumber) {
		var currentSlide,
			ret;

		if (-1 === slideNumber ) {
			return;
		}

		if (slideList[slideNumber]) {
			currentSlide = document.getElementById(slideList[slideNumber].id);
			window.scrollTo(0, currentSlide.offsetTop);
			ret = true;
		}

        return ret;
	};

	shower.isListMode = function() {
		return 'full' !== url.search.substr(1);
	};

	function normalizeSlideNumber(slideNumber) {
		if (0 > slideNumber) {
			return 0;
		} else if (slideList.length <= slideNumber) {
			return slideList.length - 1;
		} else {
			return slideNumber;
		}
	}

	shower.updateProgress = function (slideNumber) {
		if (null === progress) { return; }
		progress.style.width = (100 / (slideList.length - 1) * normalizeSlideNumber(slideNumber)).toFixed(2) + '%';
	};

	shower.updateCurrentAndPassedSlides = function(slideNumber) {
		var i, l = slideList.length, slide;
		slideNumber = normalizeSlideNumber(slideNumber);

		for ( i = 0; i < l; ++i ) {
			slide = document.getElementById(slideList[i].id);

			if ( i < slideNumber ) {
				slide.classList.remove('current');
				slide.classList.add('passed');
			} else if ( i > slideNumber ) {
				slide.classList.remove('passed');
				slide.classList.remove('current');
			} else {
				slide.classList.remove('passed');
				slide.classList.add('current');
			}
		}
	};

	shower.getSlideHash = function(slideNumber) {
		return '#' + slideList[normalizeSlideNumber(slideNumber)].id;
	};

	shower.go = function(slideNumber) {
		url.hash = shower.getSlideHash(slideNumber);

		if (!shower.isListMode()) {
			shower.updateProgress(slideNumber);
			shower.updateCurrentAndPassedSlides(slideNumber);
		}
	};

	shower.getContainingSlideId = function(el) {
		var node = el;

		while ('BODY' !== node.nodeName && 'HTML' !== node.nodeName) {
			if (node.classList.contains('slide')) {
				return node.id;
			} else {
				node = node.parentNode;
			}
		}

		return '';
	};

	// FIXME: Renaming needed? Or just some handlers rewriting?
	shower.dispatchSingleSlideMode = function(e) {
		// Process links
		// TODO: presentation links support
		if ('A' === e.target.nodeName) {
			e.preventDefault();

			window.open(e.target.getAttribute('href'));
			return;
		}

		var slideId = shower.getContainingSlideId(e.target);

		if ('' !== slideId && shower.isListMode()) {
			e.preventDefault();

			// NOTE: we should update hash to get things work properly
			url.hash = '#' + slideId;
			history.replaceState(null, null, url.pathname + '?full#' + slideId);
			shower.enterSlideMode();

			shower.updateProgress(shower.getCurrentSlideNumber());
			shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber());
			shower.runSlideshowIfPresented(shower.getCurrentSlideNumber());
		}
	};

	shower.runSlideshowIfPresented = function(slideNumber) {
		slideNumber = normalizeSlideNumber(slideNumber);

		clearTimeout(timer);

		if (slideList[slideNumber].hasTiming) {
			// Compute number of milliseconds from format "X:Y", where X is
			// number of minutes, and Y is number of seconds
			var timing = document.getElementById(slideList[slideNumber].id).dataset.timing.split(':');
			timing = parseInt(timing[0], 10) * 60 * 1000 + parseInt(timing[1], 10) * 1000;

			timer = setTimeout( function () {
				shower.go(slideNumber + 1);
				shower.runSlideshowIfPresented(slideNumber + 1);
			}, timing );
		}
	};

	// Increases inner navigation by adding 'active' class to next inactive inner navigation item
	shower.increaseInnerNavigation = function(slideNumber) {
		// Shortcut for slides without inner navigation
		if (true !== slideList[slideNumber].hasInnerNavigation) { return -1; }

		var nextNodes = document.getElementById(slideList[slideNumber].id).querySelectorAll('.next:not(.active)'),
			node;

		if (0 !== nextNodes.length) {
			node = nextNodes[0];
			node.classList.add('active');
			return nextNodes.length - 1;
		} else {
			return -1;
		}
	};

	// Event handlers

	window.addEventListener('DOMContentLoaded', function () {
		if (!shower.isListMode()) {
			// "?full" is present without slide hash, so we should display first slide
			if (-1 === shower.getCurrentSlideNumber()) {
				history.replaceState(null, null, url.pathname + '?full' + shower.getSlideHash(0));
			}

			shower.enterSlideMode();
			shower.updateProgress(shower.getCurrentSlideNumber());
			shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber());
			shower.runSlideshowIfPresented(shower.getCurrentSlideNumber());
		}
	}, false);

	window.addEventListener('popstate', function (e) {
		if (shower.isListMode()) {
			shower.enterListMode();
			shower.scrollToSlide(shower.getCurrentSlideNumber());
		} else {
			shower.enterSlideMode();
		}
	}, false);

	window.addEventListener('resize', function (e) {
		if (!shower.isListMode()) {
			shower._applyTransform(shower._getTransform());
		}
	}, false);

	document.addEventListener('keydown', function (e) {
		// Shortcut for alt, shift and meta keys
		if (e.altKey || e.ctrlKey || e.metaKey) { return; }

		var currentSlideNumber = shower.getCurrentSlideNumber(),
			innerNavigationCompleted = true;

		switch (e.which) {
			case 116: // F5
			case 13: // Enter
				if (shower.isListMode() && -1 !== currentSlideNumber) {
					e.preventDefault();

					history.pushState(null, null, url.pathname + '?full' + shower.getSlideHash(currentSlideNumber));
					shower.enterSlideMode();

					shower.updateProgress(currentSlideNumber);
					shower.updateCurrentAndPassedSlides(currentSlideNumber);
					shower.runSlideshowIfPresented(currentSlideNumber);
				}
			break;

			case 27: // Esc
				if (!shower.isListMode()) {
					e.preventDefault();

					history.pushState(null, null, url.pathname + shower.getSlideHash(currentSlideNumber));
					shower.enterListMode();
					shower.scrollToSlide(currentSlideNumber);
				}
			break;

			case 33: // PgUp
			case 38: // Up
			case 37: // Left
			case 72: // h
			case 75: // k
				e.preventDefault();
				shower.previous();
			break;

			case 34: // PgDown
			case 40: // Down
			case 39: // Right
			case 76: // l
			case 74: // j
				e.preventDefault();

				if (!shower.isListMode() ) {
					// Inner navigation is "completed" if current slide have
					// no inner navigation or inner navigation is fully shown
					innerNavigationCompleted = !slideList[currentSlideNumber].hasInnerNavigation ||
						-1 === shower.increaseInnerNavigation(currentSlideNumber);
				} else {
					// Also inner navigation is always "completed" if we are in
					// list mode
					innerNavigationCompleted = true;
				}
				// NOTE: First of all check if there is no current slide
				if (
					-1 === currentSlideNumber || innerNavigationCompleted
				) {
					currentSlideNumber++;
					shower.go(currentSlideNumber);
					// We must run slideshow only in full mode
					if (!shower.isListMode()) {
						shower.runSlideshowIfPresented(currentSlideNumber);
					}
				}
			break;

			case 36: // Home
				e.preventDefault();

				shower.first();
			break;

			case 35: // End
				e.preventDefault();

				shower.last();
			break;

			case 9: // Tab = +1; Shift + Tab = -1
			case 32: // Space = +1; Shift + Space = -1
				e.preventDefault();

				shower[e.shiftKey ? 'previous' : 'next']();
			break;

			default:
				// Behave as usual
		}
	}, false);

	document.addEventListener('click', shower.dispatchSingleSlideMode, false);
	document.addEventListener('touchend', shower.dispatchSingleSlideMode, false);

	document.addEventListener('touchstart', function (e) {
		if (!shower.isListMode()) {
			var currentSlideNumber = shower.getCurrentSlideNumber(),
				x = e.touches[0].pageX;
			if (x > window.innerWidth / 2) {
				currentSlideNumber++;
			} else {
				currentSlideNumber--;
			}

			shower.go(currentSlideNumber);
		}
	}, false);

	document.addEventListener('touchmove', function (e) {
		if (!shower.isListMode()) {
			e.preventDefault();
		}
	}, false);

    return shower;

})(this, this.document);
<commit_msg>Added primitive JSDoc to shower.next and etc.<commit_after>window.shower = (function(window, document, undefined) {
	var shower = {},
		url = window.location,
		body = document.body,
		slides = document.querySelectorAll('.slide'),
		progress = document.querySelector('div.progress div'),
		slideList = [],
		timer,
		l = slides.length, i;

	for (i = 0; i < l; i++) {
		// Slide ID's are optional. In case of missing ID we set it to the
		// slide number
		if (!slides[i].id) {
			slides[i].id = i + 1;
		}

		slideList.push({
			id: slides[i].id,
			hasInnerNavigation: null !== slides[i].querySelector('.next'),
			hasTiming: (slides[i].dataset.timing && slides[i].dataset.timing.indexOf(':') !== -1)
		});
	}

	/**
	* Get slide scale value
	* @private
	* @returns {String}
	*/
	shower._getTransform = function() {
		var denominator = Math.max(
			body.clientWidth / window.innerWidth,
			body.clientHeight / window.innerHeight
		);

		return 'scale(' + (1 / denominator) + ')';
	};

	/**
	* Set CSS transform with prefixes to body
	* @private
	* @returns {true}
	*/
	shower._applyTransform = function(transform) {
		body.style.WebkitTransform = transform;
		body.style.MozTransform = transform;
		body.style.msTransform = transform;
		body.style.OTransform = transform;
		body.style.transform = transform;

		return true;
	};

	/**
	* Show next slide. If slide is last returns false, otherwise return slide
	* number which been shown.
	* @returns {number|false}
	*/
	shower.next = function () {
		var currentSlideNumber = shower.getCurrentSlideNumber(),
			ret;

		// Only go to next slide if current slide have no inner
		// navigation or inner navigation is fully shown
		// NOTE: But first of all check if there is no current slide
		if (
			-1 === currentSlideNumber ||
			!slideList[currentSlideNumber].hasInnerNavigation ||
			-1 === shower.increaseInnerNavigation(currentSlideNumber)
		) {
			currentSlideNumber++;
			shower.go(currentSlideNumber);
			ret = currentSlideNumber + 1;
		} else {
			ret = false;
		}

		return ret;
	};

	shower.previous = function () {
		shower.go(shower.getCurrentSlideNumber() - 1);
	};

	shower.first = function() {
		shower.go(0);
	};

	shower.last = function() {
		shower.go(slideList.length - 1);
	};

	shower.enterSlideMode = function() {
		body.classList.remove('list');
		body.classList.add('full');
		shower._applyTransform(shower._getTransform());
	};

	shower.enterListMode = function() {
		body.classList.remove('full');
		body.classList.add('list');
		shower._applyTransform('none');
	};

	shower.getCurrentSlideNumber = function() {
		var i = 0,
			l = slideList.length,
			currentSlideId = url.hash.substr(1);

		for (; i < l; ++i) {
			if (currentSlideId === slideList[i].id) {
				return i;
			}
		}

		return -1;
	};

	shower.scrollToSlide = function(slideNumber) {
		var currentSlide,
			ret;

		if (-1 === slideNumber ) {
			return;
		}

		if (slideList[slideNumber]) {
			currentSlide = document.getElementById(slideList[slideNumber].id);
			window.scrollTo(0, currentSlide.offsetTop);
			ret = true;
		}

        return ret;
	};

	shower.isListMode = function() {
		return 'full' !== url.search.substr(1);
	};

	function normalizeSlideNumber(slideNumber) {
		if (0 > slideNumber) {
			return 0;
		} else if (slideList.length <= slideNumber) {
			return slideList.length - 1;
		} else {
			return slideNumber;
		}
	}

	shower.updateProgress = function (slideNumber) {
		if (null === progress) { return; }
		progress.style.width = (100 / (slideList.length - 1) * normalizeSlideNumber(slideNumber)).toFixed(2) + '%';
	};

	shower.updateCurrentAndPassedSlides = function(slideNumber) {
		var i, l = slideList.length, slide;
		slideNumber = normalizeSlideNumber(slideNumber);

		for ( i = 0; i < l; ++i ) {
			slide = document.getElementById(slideList[i].id);

			if ( i < slideNumber ) {
				slide.classList.remove('current');
				slide.classList.add('passed');
			} else if ( i > slideNumber ) {
				slide.classList.remove('passed');
				slide.classList.remove('current');
			} else {
				slide.classList.remove('passed');
				slide.classList.add('current');
			}
		}
	};

	shower.getSlideHash = function(slideNumber) {
		return '#' + slideList[normalizeSlideNumber(slideNumber)].id;
	};

	shower.go = function(slideNumber) {
		url.hash = shower.getSlideHash(slideNumber);

		if (!shower.isListMode()) {
			shower.updateProgress(slideNumber);
			shower.updateCurrentAndPassedSlides(slideNumber);
		}
	};

	shower.getContainingSlideId = function(el) {
		var node = el;

		while ('BODY' !== node.nodeName && 'HTML' !== node.nodeName) {
			if (node.classList.contains('slide')) {
				return node.id;
			} else {
				node = node.parentNode;
			}
		}

		return '';
	};

	// FIXME: Renaming needed? Or just some handlers rewriting?
	shower.dispatchSingleSlideMode = function(e) {
		// Process links
		// TODO: presentation links support
		if ('A' === e.target.nodeName) {
			e.preventDefault();

			window.open(e.target.getAttribute('href'));
			return;
		}

		var slideId = shower.getContainingSlideId(e.target);

		if ('' !== slideId && shower.isListMode()) {
			e.preventDefault();

			// NOTE: we should update hash to get things work properly
			url.hash = '#' + slideId;
			history.replaceState(null, null, url.pathname + '?full#' + slideId);
			shower.enterSlideMode();

			shower.updateProgress(shower.getCurrentSlideNumber());
			shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber());
			shower.runSlideshowIfPresented(shower.getCurrentSlideNumber());
		}
	};

	shower.runSlideshowIfPresented = function(slideNumber) {
		slideNumber = normalizeSlideNumber(slideNumber);

		clearTimeout(timer);

		if (slideList[slideNumber].hasTiming) {
			// Compute number of milliseconds from format "X:Y", where X is
			// number of minutes, and Y is number of seconds
			var timing = document.getElementById(slideList[slideNumber].id).dataset.timing.split(':');
			timing = parseInt(timing[0], 10) * 60 * 1000 + parseInt(timing[1], 10) * 1000;

			timer = setTimeout( function () {
				shower.go(slideNumber + 1);
				shower.runSlideshowIfPresented(slideNumber + 1);
			}, timing );
		}
	};

	// Increases inner navigation by adding 'active' class to next inactive inner navigation item
	shower.increaseInnerNavigation = function(slideNumber) {
		// Shortcut for slides without inner navigation
		if (true !== slideList[slideNumber].hasInnerNavigation) { return -1; }

		var nextNodes = document.getElementById(slideList[slideNumber].id).querySelectorAll('.next:not(.active)'),
			node;

		if (0 !== nextNodes.length) {
			node = nextNodes[0];
			node.classList.add('active');
			return nextNodes.length - 1;
		} else {
			return -1;
		}
	};

	// Event handlers

	window.addEventListener('DOMContentLoaded', function () {
		if (!shower.isListMode()) {
			// "?full" is present without slide hash, so we should display first slide
			if (-1 === shower.getCurrentSlideNumber()) {
				history.replaceState(null, null, url.pathname + '?full' + shower.getSlideHash(0));
			}

			shower.enterSlideMode();
			shower.updateProgress(shower.getCurrentSlideNumber());
			shower.updateCurrentAndPassedSlides(shower.getCurrentSlideNumber());
			shower.runSlideshowIfPresented(shower.getCurrentSlideNumber());
		}
	}, false);

	window.addEventListener('popstate', function (e) {
		if (shower.isListMode()) {
			shower.enterListMode();
			shower.scrollToSlide(shower.getCurrentSlideNumber());
		} else {
			shower.enterSlideMode();
		}
	}, false);

	window.addEventListener('resize', function (e) {
		if (!shower.isListMode()) {
			shower._applyTransform(shower._getTransform());
		}
	}, false);

	document.addEventListener('keydown', function (e) {
		// Shortcut for alt, shift and meta keys
		if (e.altKey || e.ctrlKey || e.metaKey) { return; }

		var currentSlideNumber = shower.getCurrentSlideNumber(),
			innerNavigationCompleted = true;

		switch (e.which) {
			case 116: // F5
			case 13: // Enter
				if (shower.isListMode() && -1 !== currentSlideNumber) {
					e.preventDefault();

					history.pushState(null, null, url.pathname + '?full' + shower.getSlideHash(currentSlideNumber));
					shower.enterSlideMode();

					shower.updateProgress(currentSlideNumber);
					shower.updateCurrentAndPassedSlides(currentSlideNumber);
					shower.runSlideshowIfPresented(currentSlideNumber);
				}
			break;

			case 27: // Esc
				if (!shower.isListMode()) {
					e.preventDefault();

					history.pushState(null, null, url.pathname + shower.getSlideHash(currentSlideNumber));
					shower.enterListMode();
					shower.scrollToSlide(currentSlideNumber);
				}
			break;

			case 33: // PgUp
			case 38: // Up
			case 37: // Left
			case 72: // h
			case 75: // k
				e.preventDefault();
				shower.previous();
			break;

			case 34: // PgDown
			case 40: // Down
			case 39: // Right
			case 76: // l
			case 74: // j
				e.preventDefault();

				if (!shower.isListMode() ) {
					// Inner navigation is "completed" if current slide have
					// no inner navigation or inner navigation is fully shown
					innerNavigationCompleted = !slideList[currentSlideNumber].hasInnerNavigation ||
						-1 === shower.increaseInnerNavigation(currentSlideNumber);
				} else {
					// Also inner navigation is always "completed" if we are in
					// list mode
					innerNavigationCompleted = true;
				}
				// NOTE: First of all check if there is no current slide
				if (
					-1 === currentSlideNumber || innerNavigationCompleted
				) {
					currentSlideNumber++;
					shower.go(currentSlideNumber);
					// We must run slideshow only in full mode
					if (!shower.isListMode()) {
						shower.runSlideshowIfPresented(currentSlideNumber);
					}
				}
			break;

			case 36: // Home
				e.preventDefault();

				shower.first();
			break;

			case 35: // End
				e.preventDefault();

				shower.last();
			break;

			case 9: // Tab = +1; Shift + Tab = -1
			case 32: // Space = +1; Shift + Space = -1
				e.preventDefault();

				shower[e.shiftKey ? 'previous' : 'next']();
			break;

			default:
				// Behave as usual
		}
	}, false);

	document.addEventListener('click', shower.dispatchSingleSlideMode, false);
	document.addEventListener('touchend', shower.dispatchSingleSlideMode, false);

	document.addEventListener('touchstart', function (e) {
		if (!shower.isListMode()) {
			var currentSlideNumber = shower.getCurrentSlideNumber(),
				x = e.touches[0].pageX;
			if (x > window.innerWidth / 2) {
				currentSlideNumber++;
			} else {
				currentSlideNumber--;
			}

			shower.go(currentSlideNumber);
		}
	}, false);

	document.addEventListener('touchmove', function (e) {
		if (!shower.isListMode()) {
			e.preventDefault();
		}
	}, false);

    return shower;

})(this, this.document);
<|endoftext|>


<commit_before>// Search //

var Timer;
var Timer2;
var same = "";
var count = 0;
var started = false;
var parse = [];
var soke = "";
var pages = [];
var numberOfPages = 0;
var rankedHits = [];
var show;
loadDoc(pages,'content.txt',0,'txt');

function dropDown(whatPage,splitWord){
	var div = document.getElementById('dropdown');
	div.innerHTML = "";
	for(var i = 0; i < whatPage.length; i++){
		var a = document.createElement("a");
		a.setAttribute("href",'?'+whatPage[i]);
		a.innerHTML = splitWord[0];
		div.appendChild(a);
	}
	var show = document.getElementById("dropdown");
	show.style.display = 'block';
}

function close1Index(splitWord){
	var hits = [];
	for(var h = 0; h < splitWord.length; h++){
		hits[h]=[];
		var number = 0;
		for(var i = 0; i < parse.length; i++){
		loop1:for(var j = 0; j < parse[i].length; j++){
				if(splitWord[h]==parse[i][j]){
					console.log('hit')
					hits[h][number] = pages[0][i];
					number = number + 1;
					break loop1;
				}
			}
		}
	}
	hits.sort();
	var number1 = 0;
	var whatPage = [];
	for(var h = 0; h < hits[0].length; h++){
		whatPage[h] = hits[0][h];
		number1 = number1 + 1;
		for(var i = 1; i < hits.length; i++){
			loop2:for(var j = 0; j < hits[i].length; j++){
				if(hits[0][h] == hits[i][j]){
					number1 = number1 + 1;
					break loop2;
				}
			}
		}
	}
	if((number1/whatPage.length)==splitWord.length){
		console.log('Hurra')
	}
	dropDown(whatPage,splitWord);
}

function moreWords(searchString){
	var splitWord = searchString.split(" ");
	close1Index(splitWord);
}

function loadDoc(listSave,page,numberOfPage) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
		var page1 = [];
		var fileString = this.responseText;
		var cleanString = fileString.replace(/[\?\|!"#¤%&\/\(\)=\+-\.,'¨\^}{\[\]\$£@:;*`~€<>§]| (?= )/g, " ");
		var cleanerString = cleanString.replace(/[A-Z]/gi, function myFunction(x){return x.toLowerCase();});
		var word = [];
		var lines = cleanerString.split("\n");
		var words = [];
		for (var i = 0; i < lines.length; i++){
			words.push(lines[i].split(" "));
		}
		for(var i = 0; i < words.length; i++){
			for(var j = 0; j < words[i].length; j++){
				word.push(words[i][j]);
			}
		}
		for(var i = 0; i < word.length; i++){
			page1[i] = word[i];
		}
		listSave[numberOfPage] = page1;
	}
  };
  xhttp.open("GET", "https://build\-a\-pc\.github\.io\\"+page, true);
  xhttp.send();
}

function checkTextBox(){
	var page = 1;
	var searchString = document.getElementById('search');
	if(searchString.value !== ''){
		if(same == searchString.value){
			count = count+1;
		}
		same = searchString.value;
	}
	if(count == 2){
		clearInterval(Timer);
		started = false;
		console.log('3 times');
		same = "";
		count = 0;
		soke = searchString;
		var cleanSearchString = searchString.value.replace(/[A-Z]/gi, function myFunction(x){return x.toLowerCase();});
		moreWords(cleanSearchString);
		/**for(i = 0; i < parse.length; i++){
			loop3:for(var j = 0; j < parse[i].length; j++){
				if(cleanSearchString==parse[i][j]){
					console.log('We have a match at page: ' + pages[0][i] +" " + parse[i][j]);
					break loop3;
				}
			}**/

		}
}

function start(){
	if(!started){
		started = true;
		Timer = setInterval(checkTextBox, 1000);
		for(var i = 0; i < pages[0].length;i++){
			loadDoc(parse,'pages\\'+pages[0][i]+'.inc.html',i,'html')
		}
	}
	var show = document.getElementById("dropdown");
	show.style.display = 'none';
}

function stop(){
	started = false;
	clearInterval(Timer);
	show = document.getElementById("dropdown");
	Timer2 = setInterval(checkTextBox, 1000);
}

function hideDropDown(){
	show.style.display = 'none';
	clearInterval(Timer2);
}<commit_msg>Updated of clickble<commit_after>// Search //

var Timer;
var Timer2;
var same = "";
var count = 0;
var started = false;
var parse = [];
var soke = "";
var pages = [];
var numberOfPages = 0;
var rankedHits = [];
var show;
loadDoc(pages,'content.txt',0,'txt');

function dropDown(whatPage,splitWord){
	var div = document.getElementById('dropdown');
	div.innerHTML = "";
	for(var i = 0; i < whatPage.length; i++){
		var a = document.createElement("a");
		a.setAttribute("href",'?'+whatPage[i]);
		a.innerHTML = splitWord[0];
		div.appendChild(a);
	}
	var show = document.getElementById("dropdown");
	show.style.display = 'block';
}

function close1Index(splitWord){
	var hits = [];
	for(var h = 0; h < splitWord.length; h++){
		hits[h]=[];
		var number = 0;
		for(var i = 0; i < parse.length; i++){
		loop1:for(var j = 0; j < parse[i].length; j++){
				if(splitWord[h]==parse[i][j]){
					console.log('hit')
					hits[h][number] = pages[0][i];
					number = number + 1;
					break loop1;
				}
			}
		}
	}
	hits.sort();
	var number1 = 0;
	var whatPage = [];
	for(var h = 0; h < hits[0].length; h++){
		whatPage[h] = hits[0][h];
		number1 = number1 + 1;
		for(var i = 1; i < hits.length; i++){
			loop2:for(var j = 0; j < hits[i].length; j++){
				if(hits[0][h] == hits[i][j]){
					number1 = number1 + 1;
					break loop2;
				}
			}
		}
	}
	if((number1/whatPage.length)==splitWord.length){
		console.log('Hurra')
	}
	dropDown(whatPage,splitWord);
}

function moreWords(searchString){
	var splitWord = searchString.split(" ");
	close1Index(splitWord);
}

function loadDoc(listSave,page,numberOfPage) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
		var page1 = [];
		var fileString = this.responseText;
		var cleanString = fileString.replace(/[\?\|!"#¤%&\/\(\)=\+-\.,'¨\^}{\[\]\$£@:;*`~€<>§]| (?= )/g, " ");
		var cleanerString = cleanString.replace(/[A-Z]/gi, function myFunction(x){return x.toLowerCase();});
		var word = [];
		var lines = cleanerString.split("\n");
		var words = [];
		for (var i = 0; i < lines.length; i++){
			words.push(lines[i].split(" "));
		}
		for(var i = 0; i < words.length; i++){
			for(var j = 0; j < words[i].length; j++){
				word.push(words[i][j]);
			}
		}
		for(var i = 0; i < word.length; i++){
			page1[i] = word[i];
		}
		listSave[numberOfPage] = page1;
	}
  };
  xhttp.open("GET", "https://build\-a\-pc\.github\.io\\"+page, true);
  xhttp.send();
}

function checkTextBox(){
	var page = 1;
	var searchString = document.getElementById('search');
	if(searchString.value !== ''){
		if(same == searchString.value){
			count = count+1;
		}
		same = searchString.value;
	}
	if(count == 2){
		clearInterval(Timer);
		started = false;
		console.log('3 times');
		same = "";
		count = 0;
		soke = searchString;
		var cleanSearchString = searchString.value.replace(/[A-Z]/gi, function myFunction(x){return x.toLowerCase();});
		moreWords(cleanSearchString);
		/**for(i = 0; i < parse.length; i++){
			loop3:for(var j = 0; j < parse[i].length; j++){
				if(cleanSearchString==parse[i][j]){
					console.log('We have a match at page: ' + pages[0][i] +" " + parse[i][j]);
					break loop3;
				}
			}**/

		}
}

function start(){
	if(!started){
		started = true;
		Timer = setInterval(checkTextBox, 1000);
		for(var i = 0; i < pages[0].length;i++){
			loadDoc(parse,'pages\\'+pages[0][i]+'.inc.html',i,'html')
		}
	}
	var show = document.getElementById("dropdown");
	show.style.display = 'none';
}

function stop(){
	started = false;
	clearInterval(Timer);
	show = document.getElementById("dropdown");
	Timer2 = setInterval(hideDropDown, 500);
}

function hideDropDown(){
	show.style.display = 'none';
	clearInterval(Timer2);
}<|endoftext|>


<commit_before>const express = require('express')
const path = require('path')

const app = express()
const port = process.env.PORT || 8000

if (process.env.NODE_ENV !== 'production') {
  const webpack = require('webpack')
  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpackHotMiddleware = require('webpack-hot-middleware')
  const config = require('./webpack.config')
  const compiler = webpack(config)

  app.use(webpackDevMiddleware(compiler, {
    noInfo: true
  }))

  app.use(webpackHotMiddleware(compiler))
} else {
  app.get('/litewrite.min.js', function (req, res) {
    res.sendFile(path.join(__dirname, '../litewrite.min.js'))
  })
}

function serveFile (relativePath) {
  return function (req, res) {
    res.sendFile(path.join(__dirname, '..', relativePath))
  }
}

app.get('/', serveFile('index.html'))
app.use('/img', express.static(path.join(__dirname, '../img')))
app.use('/style', express.static(path.join(__dirname, '../style')))
app.get('/cache.manifest', serveFile('cache.manifest'))

if (require.main === module) {
  app.listen(port, function (error) {
    if (error) {
      console.error(error)
    } else {
      console.info('==> 🌎  Listening on port %s. Open up http://localhost:%s/ in your browser.', port, port)
    }
  })
}

module.exports = app
<commit_msg>Micro-cleanup in server.js<commit_after>const express = require('express')
const path = require('path')

const app = express()
const port = process.env.PORT || 8000

function serveFile (relativePath) {
  return function (req, res) {
    res.sendFile(path.join(__dirname, '..', relativePath))
  }
}

if (process.env.NODE_ENV !== 'production') {
  const webpack = require('webpack')
  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpackHotMiddleware = require('webpack-hot-middleware')
  const config = require('./webpack.config')
  const compiler = webpack(config)

  app.use(webpackDevMiddleware(compiler, {
    noInfo: true
  }))

  app.use(webpackHotMiddleware(compiler))
} else {
  app.get('/litewrite.min.js', serveFile('litewrite.min.js'))
}

app.get('/', serveFile('index.html'))
app.use('/img', express.static(path.join(__dirname, '../img')))
app.use('/style', express.static(path.join(__dirname, '../style')))
app.get('/cache.manifest', serveFile('cache.manifest'))

if (require.main === module) {
  app.listen(port, function (error) {
    if (error) {
      console.error(error)
    } else {
      console.info('==> 🌎  Listening on port %s. Open up http://localhost:%s/ in your browser.', port, port)
    }
  })
}

module.exports = app
<|endoftext|>