<commit_before>// Load the Visualization API and the corechart package.
 google.charts.load('current', {'packages':['timeline']});

// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
  console.log('drawing chart')

  // Create the data table.
  var data = new google.visualization.DataTable();
  var now = new Date();
  data.addColumn({type: 'string', id: 'Category'});
  data.addColumn({type: 'string', id: 'Item'});
  data.addColumn({type: 'date', id: 'Start'});
  data.addColumn({type: 'date', id: 'End'});
  data.addRows([
    ['Language', 'JavaScript', new Date(2015,6,1), now],
    ['Language', 'Ruby', new Date(2015,10,9), now],
    ['Language', 'HTML', new Date(2015,10,9), now],
    ['Language', 'CSS', new Date(2015,10,9), now],
    ['Language', 'Java', new Date(2012,6,1), new Date(2015,0,1)],
    ['Language', 'C', new Date(2012,2,1), new Date(2012,6,1)],
    ['Language', 'Perl', new Date(2012,6,1), new Date(2012,10,1)],
    ['Language', 'Unix shell script', new Date(2012,6,1), new Date(2012,10,1)],
    ['Framework', 'Ruby on Rails', new Date(2015,10,9), now],
    ['Framework', 'Backbone.js', new Date(2015,10,9), now],
    ['Framework', 'Sinatra', new Date(2015,10,9), now],
    ['Framework', 'Spring', new Date(2014,7,0), new Date(2014,11,1)],
    ['Framework', 'Struts', new Date(2014,3,1), new Date(2014,6,1)],
    ['Library', 'jQuery', new Date(2015,10,9), now],
    ['Library', 'Underscore.js', new Date(2015,10,9), now],
    ['Testing', 'Minitest', new Date(2015,10,9), now],
    ['Testing', 'RSpec', new Date(2015,10,9), now],
    ['Database', 'PostgreSQL', new Date(2015,10,9), now],
    ['Database', 'Sqlite', new Date(2015,10,9), now],
    ['Database', 'MongoDB', new Date(2014,7,0), new Date(2014,11,1)],
    ['Database', 'Neo4j', new Date(2014,7,0), new Date(2014,11,1)],
    ['Other', 'REST', new Date(2015,10,9), now],
    ['Other', 'AJAX', new Date(2015,10,9), now],
    ['Other', 'Git', new Date(2015,10,9), now],
    ['Other', 'Agile', new Date(2015,7,26), new Date(2015,9,11)],
    ['Other', 'Algorithms', new Date(2013,6,1), new Date(2013,10,1)],
    ['Other', 'OO Design', new Date(2014,2,1), new Date(2014,6,1)],
    ['Other', 'Data structures', new Date(2012,6,1), new Date(2012,10,1)],
    ['Other', 'Networks', new Date(2013,2,1), new Date(2013,6,1)]
  ]);

  // Set chart options
  var options = {
    'backgroundColor': 'transparent',
    'timeline': { colorByRowLabel: true },
    'forceIFrame': true,
    'fontName': 'verdana'
  };

  // Instantiate and draw our chart, passing in some options.
  var container = document.getElementById('skills_chart_container');
  var chart = new google.visualization.Timeline(container);
  chart.draw(data, options);
}

$(document).ready(function() {
    $('#fullpage').fullpage({
      responsiveHeight: 570,
      responsiveWidth: 640,
      anchors: ['home', 'me', 'skill', 'project', '5th', '6th', '7th', 'contact'],
      menu: '#menu',
      normalScrollElements: 'iframe',
      afterRender: function() {
        // show background image only after it's downloaded
        $('.brief').hide();
        $('<img/>').attr('src', 'images/desk.jpg').load(function() {
          $(this).remove(); // prevent memory leaks as @benweet suggested
          $('.brief').css('background-image', 'url(images/desk.jpg)').hide().fadeIn(1000, function() {
            $('.section').show();
            // Set a callback to run when the Google Visualization API is loaded.
            google.charts.setOnLoadCallback(drawChart);
          });
        });
      }
    });

    // pan & zoom project images
    aspectRatio = 1024 / 768;
    $('.project .img').on('mousemove', function(e) {
      // position of image container relative to document
      var elementPos = $(this).offset();
      // x position relative to top left of image container
      var imgX = e.pageX - Math.floor(elementPos.left);
      var imgY = e.pageY - Math.floor(elementPos.top);

      // width of image is always 100% of image container
      var imgWidth = $(this).width();
      // height changes according to image container
      var imgHeight = Math.floor(imgWidth / aspectRatio);

      // move image in opposite direction when panning. scale according to
      // background-size below
      var newX = -imgX * 2;
      var newY = -imgY * 2;

      // when cursor position is beyond image size, stop panning
      if (Math.abs(newX) > imgWidth) { newX = -imgWidth; }
      if (Math.abs(newY) > imgHeight) { newY = -imgHeight; }

      $(this).css('background-size', '200%');
      $(this).css('background-position', newX + 'px ' + newY + 'px');
    })

    $('.project .img').on('mouseleave', function(){
      $(this).css('background-position', 'center');
      $(this).css('background-size', 'contain');
    });

    $('#menu li:first-child').on('click', function(){
      $('#menu li').toggleClass('showMenuItem');
    });

    $('#menu li:not(:first)').on('click', function(e){
      if (e.button === 0) {
        $('#menu li:not(:first)').removeClass('showMenuItem');
      }
    });

    $('#menu').on('mouseleave', function(){
      $('#menu li:not(:first)').removeClass('showMenuItem');
    });

});

$(window).resize(function(){
  drawChart();
});
<commit_msg>Undo change<commit_after>// Load the Visualization API and the corechart package.
 google.charts.load('current', {'packages':['timeline']});

// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
  console.log('drawing chart')

  // Create the data table.
  var data = new google.visualization.DataTable();
  var now = new Date();
  data.addColumn({type: 'string', id: 'Category'});
  data.addColumn({type: 'string', id: 'Item'});
  data.addColumn({type: 'date', id: 'Start'});
  data.addColumn({type: 'date', id: 'End'});
  data.addRows([
    ['Language', 'JavaScript', new Date(2015,6,1), now],
    ['Language', 'Ruby', new Date(2015,10,9), now],
    ['Language', 'HTML', new Date(2015,10,9), now],
    ['Language', 'CSS', new Date(2015,10,9), now],
    ['Language', 'Java', new Date(2012,6,1), new Date(2015,0,1)],
    ['Language', 'C', new Date(2012,2,1), new Date(2012,6,1)],
    ['Language', 'Perl', new Date(2012,6,1), new Date(2012,10,1)],
    ['Language', 'Unix shell script', new Date(2012,6,1), new Date(2012,10,1)],
    ['Framework', 'Ruby on Rails', new Date(2015,10,9), now],
    ['Framework', 'Backbone.js', new Date(2015,10,9), now],
    ['Framework', 'Sinatra', new Date(2015,10,9), now],
    ['Framework', 'Spring', new Date(2014,7,0), new Date(2014,11,1)],
    ['Framework', 'Struts', new Date(2014,3,1), new Date(2014,6,1)],
    ['Library', 'jQuery', new Date(2015,10,9), now],
    ['Library', 'Underscore.js', new Date(2015,10,9), now],
    ['Testing', 'Minitest', new Date(2015,10,9), now],
    ['Testing', 'RSpec', new Date(2015,10,9), now],
    ['Database', 'PostgreSQL', new Date(2015,10,9), now],
    ['Database', 'Sqlite', new Date(2015,10,9), now],
    ['Database', 'MongoDB', new Date(2014,7,0), new Date(2014,11,1)],
    ['Database', 'Neo4j', new Date(2014,7,0), new Date(2014,11,1)],
    ['Other', 'REST', new Date(2015,10,9), now],
    ['Other', 'AJAX', new Date(2015,10,9), now],
    ['Other', 'Git', new Date(2015,10,9), now],
    ['Other', 'Agile', new Date(2015,7,26), new Date(2015,9,11)],
    ['Other', 'Algorithms', new Date(2013,6,1), new Date(2013,10,1)],
    ['Other', 'OO Design', new Date(2014,2,1), new Date(2014,6,1)],
    ['Other', 'Data structures', new Date(2012,6,1), new Date(2012,10,1)],
    ['Other', 'Networks', new Date(2013,2,1), new Date(2013,6,1)]
  ]);

  // Set chart options
  var options = {
    'backgroundColor': 'transparent',
    'timeline': { colorByRowLabel: true },
    'forceIFrame': true,
    'fontName': 'verdana'
  };

  // Instantiate and draw our chart, passing in some options.
  var container = document.getElementById('skills_chart_container');
  var chart = new google.visualization.Timeline(container);
  chart.draw(data, options);
}

$(document).ready(function() {
    $('#fullpage').fullpage({
      responsiveHeight: 570,
      responsiveWidth: 640,
      anchors: ['home', 'me', 'skill', 'project', '5th', '6th', '7th', 'contact'],
      menu: '#menu',
      normalScrollElements: 'iframe',
      afterRender: function() {
        // show background image only after it's downloaded
        $('<img/>').attr('src', 'images/desk.jpg').load(function() {
          $(this).remove(); // prevent memory leaks as @benweet suggested
          $('.brief').css('background-image', 'url(images/desk.jpg)').hide().fadeIn(1000, function() {
            $('.section').show();
            // Set a callback to run when the Google Visualization API is loaded.
            google.charts.setOnLoadCallback(drawChart);
          });
        });
      }
    });

    // pan & zoom project images
    aspectRatio = 1024 / 768;
    $('.project .img').on('mousemove', function(e) {
      // position of image container relative to document
      var elementPos = $(this).offset();
      // x position relative to top left of image container
      var imgX = e.pageX - Math.floor(elementPos.left);
      var imgY = e.pageY - Math.floor(elementPos.top);

      // width of image is always 100% of image container
      var imgWidth = $(this).width();
      // height changes according to image container
      var imgHeight = Math.floor(imgWidth / aspectRatio);

      // move image in opposite direction when panning. scale according to
      // background-size below
      var newX = -imgX * 2;
      var newY = -imgY * 2;

      // when cursor position is beyond image size, stop panning
      if (Math.abs(newX) > imgWidth) { newX = -imgWidth; }
      if (Math.abs(newY) > imgHeight) { newY = -imgHeight; }

      $(this).css('background-size', '200%');
      $(this).css('background-position', newX + 'px ' + newY + 'px');
    })

    $('.project .img').on('mouseleave', function(){
      $(this).css('background-position', 'center');
      $(this).css('background-size', 'contain');
    });

    $('#menu li:first-child').on('click', function(){
      $('#menu li').toggleClass('showMenuItem');
    });

    $('#menu li:not(:first)').on('click', function(e){
      if (e.button === 0) {
        $('#menu li:not(:first)').removeClass('showMenuItem');
      }
    });

    $('#menu').on('mouseleave', function(){
      $('#menu li:not(:first)').removeClass('showMenuItem');
    });

});

$(window).resize(function(){
  drawChart();
});
<|endoftext|>


<commit_before>/*global GIGO, jQuery,  window,  alert,  Browser */
/*jslint browser: true */
/*properties mirrors, site, loc, provider, url, hide */

/* js lint complains about UTF8 characters in Cyrillic and Japanese.  I am ignoring that complaint.
I have seen no feedback that says the text shows up incorrectly. */

GIGO.mirrors = [{
    "site": "test-ipv6.com",
    "loc": "US CA",
    "provider": "Jason Fesler",
    "hide": 0
}, {
    "site": "test-ipv6.asnet.am",
    "loc": "AM",
    "provider": "Academic Scientific Research Computer Network of Armenia",
    "hide": 1
}, {
    "site": "test-ipv6.at",
    "loc": "AT",
    "provider": "Silver Server GmbH",
    "hide": 1
}, {
    "site": "test-ipv6.waia.asn.au",
    "loc": "AU",
    "provider": "Western Australian Internet Association",
    "hide": 1
}, {
    "site": "test-ipv6.cz",
    "loc": "CZ",
    "provider": "nic.cz",
    "hide": 0
}, {
    "site": "test-ipv6.monash.edu",
    "loc": "AU",
    "provider": "Monash University",
    "hide": 0
}, {
    "site": "test-ipv6.ceengine.eu",
    "loc": "RO",
    "provider": "Central and Eastern European Networking Engine",
    "hide": 0
}, {
    "site": "test-ipv6.internet.fo",
    "loc": "FO",
    "provider": "Faroese Telecom",
    "hide": 1
}, {
    "site": "test-ipv6.sth.sze.hu",
    "loc": "HU",
    "provider": "NetClub, Szechenyi Istvan University",
    "hide": 1
}, {
    "site": "test-ipv6.carnet.hr",
    "loc": "HR",
    "provider": "Croatian Academic and Research Network",
    "hide": 0
}, {
    "site": "test-ipv6.hu",
    "loc": "HU",
    "provider": "Polaris-N Systems",
    "hide": 0
}, {
    "site": "test-ipv6.jp",
    "loc": "JP",
    "provider": "CLARA ONLINE, Inc",
    "hide": 0
}, {
    "site": "test-ipv6.nl",
    "loc": "NL",
    "provider": "BIT BV",
    "hide": 0
}, {
    "site": "test-ipv6.roedu.net",
    "loc": "RO",
    "provider": "RoEduNet",
    "hide": 0
}, {
    "site": "test-ipv6.ro",
    "loc": "RO",
    "provider": "RCS & RDS",
    "skipsites": 1,
    "hide": 0
}, {
    "site": "test-ipv6.se",
    "loc": "SE",
    "provider": "Interlan Gefle AB",
    "hide": 0
}, {
    "site": "test-ipv6.ams.vr.org",
    "loc": "NL",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.chi.vr.org",
    "loc": "US IL",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.iad.vr.org",
    "loc": "US VA",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.sjc.vr.org",
    "loc": "US CA",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.ceengine.eu",
    "loc": "RO",
    "provider": "Central and Eastern European Networking Engine",
    "hide": 0
}, {
    "site": "test-ipv6.chiveworthy.com",
    "loc": "US WI",
    "provider": "Dale Hartung",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "test-ipv6.gremlin.ca",
    "loc": "CA",
    "provider": "Scott Logan",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "ipv6-test.co.uk",
    "loc": "UK",
    "provider": "BSC-Telecom",
    "skipsites": 1,
    "hide": 0
}, {
    "site": "test-ipv6.edu.cn",
    "loc": "CN",
    "provider": "CERNET",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "test-ipv6.vyncke.org",
    "loc": "FR",
    "provider": "Éric Vyncke",
    "hide": 0
}, {
    "site": "test-ipv6.si",
    "loc": "SI",
    "provider": "Damjan Sirnik",
    "hide": 0
}, {
    "site": "test-ipv6.showmyip.ca",
    "loc": "UK",
    "provider": "Christopher Munz-Michielin",
    "hide": 0
}, {
    "site": "test-ipv6.no",
    "loc": "NO",
    "provider": "Availo AS",
    "hide": 0
}, {
    "site": "test-ipv6.co.za",
    "loc": "ZA",
    "provider": "Neology",
    "hide": 0
}, {
    "site": "test-ipv6.vtt.net",
    "loc": "RU",
    "provider": "JSC \"Volgatranstelecom\"",
    "hide": 0
}, {
    "site": "test-ipv6.vn.ua",
    "loc": "UA",
    "provider": "IP-Connect LLC",
    "hide": 0
}, {
    "site": "test-ipv6.go6.si",
    "loc": "SI",
    "provider": "Go6 Lab - Slovenian IPv6 Iniciative",
    "hide": 0
}, {
    "site": "v6research.net",
    "loc": "US",
    "provider": "Bill Cerveny",
    "hide": 0
}, {
    "site": "test-ipv6.tld.sk",
    "loc": "SK",
    "provider": "Sk-nic",
    "hide": 0
}, {
    "site": "testipv6.de",
    "loc": "DE",
    "provider": "COSIMO Vertriebs -und Beratungs GmbH",
    "hide": 0
}, {
    "site": "test-ipv6.belwue.net",
    "loc": "DE",
    "provider": "BelWü",
    "hide": 0
}, {
    "site": "test-ipv6.uni-ruse.bg",
    "loc": "BG",
    "provider": "University of Ruse",
    "hide": 0
}, {
    "site": "sixte.st",
    "loc": "SG",
    "provider": "Delan Azabani",
    "hide": 0
}];
<commit_msg>New mirror!<commit_after>/*global GIGO, jQuery,  window,  alert,  Browser */
/*jslint browser: true */
/*properties mirrors, site, loc, provider, url, hide */

/* js lint complains about UTF8 characters in Cyrillic and Japanese.  I am ignoring that complaint.
I have seen no feedback that says the text shows up incorrectly. */

GIGO.mirrors = [{
    "site": "test-ipv6.com",
    "loc": "US CA",
    "provider": "Jason Fesler",
    "hide": 0
}, {
    "site": "test-ipv6.asnet.am",
    "loc": "AM",
    "provider": "Academic Scientific Research Computer Network of Armenia",
    "hide": 1
}, {
    "site": "test-ipv6.at",
    "loc": "AT",
    "provider": "Silver Server GmbH",
    "hide": 1
}, {
    "site": "test-ipv6.waia.asn.au",
    "loc": "AU",
    "provider": "Western Australian Internet Association",
    "hide": 1
}, {
    "site": "test-ipv6.cz",
    "loc": "CZ",
    "provider": "nic.cz",
    "hide": 0
}, {
    "site": "test-ipv6.monash.edu",
    "loc": "AU",
    "provider": "Monash University",
    "hide": 0
}, {
    "site": "test-ipv6.ceengine.eu",
    "loc": "RO",
    "provider": "Central and Eastern European Networking Engine",
    "hide": 0
}, {
    "site": "test-ipv6.internet.fo",
    "loc": "FO",
    "provider": "Faroese Telecom",
    "hide": 1
}, {
    "site": "test-ipv6.sth.sze.hu",
    "loc": "HU",
    "provider": "NetClub, Szechenyi Istvan University",
    "hide": 1
}, {
    "site": "test-ipv6.carnet.hr",
    "loc": "HR",
    "provider": "Croatian Academic and Research Network",
    "hide": 0
}, {
    "site": "test-ipv6.hu",
    "loc": "HU",
    "provider": "Polaris-N Systems",
    "hide": 0
}, {
    "site": "test-ipv6.jp",
    "loc": "JP",
    "provider": "CLARA ONLINE, Inc",
    "hide": 0
}, {
    "site": "test-ipv6.nl",
    "loc": "NL",
    "provider": "BIT BV",
    "hide": 0
}, {
    "site": "test-ipv6.roedu.net",
    "loc": "RO",
    "provider": "RoEduNet",
    "hide": 0
}, {
    "site": "test-ipv6.ro",
    "loc": "RO",
    "provider": "RCS & RDS",
    "skipsites": 1,
    "hide": 0
}, {
    "site": "test-ipv6.se",
    "loc": "SE",
    "provider": "Interlan Gefle AB",
    "hide": 0
}, {
    "site": "test-ipv6.ams.vr.org",
    "loc": "NL",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.chi.vr.org",
    "loc": "US IL",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.iad.vr.org",
    "loc": "US VA",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.sjc.vr.org",
    "loc": "US CA",
    "provider": "vr.org",
    "hide": 0
}, {
    "site": "test-ipv6.ceengine.eu",
    "loc": "RO",
    "provider": "Central and Eastern European Networking Engine",
    "hide": 0
}, {
    "site": "test-ipv6.chiveworthy.com",
    "loc": "US WI",
    "provider": "Dale Hartung",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "test-ipv6.gremlin.ca",
    "loc": "CA",
    "provider": "Scott Logan",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "ipv6-test.co.uk",
    "loc": "UK",
    "provider": "BSC-Telecom",
    "skipsites": 1,
    "hide": 0
}, {
    "site": "test-ipv6.edu.cn",
    "loc": "CN",
    "provider": "CERNET",
    "skipsites": 0,
    "hide": 0
}, {
    "site": "test-ipv6.vyncke.org",
    "loc": "FR",
    "provider": "Éric Vyncke",
    "hide": 0
}, {
    "site": "test-ipv6.si",
    "loc": "SI",
    "provider": "Damjan Sirnik",
    "hide": 0
}, {
    "site": "test-ipv6.showmyip.ca",
    "loc": "UK",
    "provider": "Christopher Munz-Michielin",
    "hide": 0
}, {
    "site": "test-ipv6.no",
    "loc": "NO",
    "provider": "Availo AS",
    "hide": 0
}, {
    "site": "test-ipv6.co.za",
    "loc": "ZA",
    "provider": "Neology",
    "hide": 0
}, {
    "site": "test-ipv6.vtt.net",
    "loc": "RU",
    "provider": "JSC \"Volgatranstelecom\"",
    "hide": 0
}, {
    "site": "test-ipv6.vn.ua",
    "loc": "UA",
    "provider": "IP-Connect LLC",
    "hide": 0
}, {
    "site": "test-ipv6.go6.si",
    "loc": "SI",
    "provider": "Go6 Lab - Slovenian IPv6 Iniciative",
    "hide": 0
}, {
    "site": "v6research.net",
    "loc": "US",
    "provider": "Bill Cerveny",
    "hide": 0
}, {
    "site": "test-ipv6.tld.sk",
    "loc": "SK",
    "provider": "Sk-nic",
    "hide": 0
}, {
    "site": "testipv6.de",
    "loc": "DE",
    "provider": "COSIMO Vertriebs -und Beratungs GmbH",
    "hide": 0
}, {
    "site": "test-ipv6.belwue.net",
    "loc": "DE",
    "provider": "BelWü",
    "hide": 0
}, {
    "site": "test-ipv6.uni-ruse.bg",
    "loc": "BG",
    "provider": "University of Ruse",
    "hide": 0
}, {
    "site": "sixte.st",
    "loc": "SG",
    "provider": "Delan Azabani",
    "hide": 0
}, {
    "site": "test-ipv6.alpinedc.ch",
    "loc": "CH",
    "provider": "AlpineDC",
    "hide": 0
}];
<|endoftext|>


<commit_before>/**
 * ngul 0.4
 * Copyright 2013 Kamalakar Gadireddy. and other contributors; https://github.com/gkodes/ngul
 * @license: MIT
 */

(function(angular, nu) {
'use strict';
/*global nu, angular: true, FileReader: true*/
  var list = angular.module('nu.list', []);
  list.directive('nuList', [
    function() { // try to rename it to collection or list
      return {
        template: '

',
        restrict: 'EACM', // 145 550 ? 12118
        replace: true,
        controller: ['$scope', '$element', '$attrs', function($scope, $element) {
          this.$render = angular.noop; // invokde for rending an element, expected an compiler
          this.$filter = angular.noop; // invokde before render if return false wont render that element
          this.$link = angular.noop; // invokde after render with the element

          this.$indexOf = angular.noop;
          var nuList = this;

          var render = function(item) {
            var node = nuList.$render(item);
            node.data('src', item);
            nuList.$link(node);
          };

          this.$indexOf = function(node) {
            for(var i = 0; i < nuList.$src.length; i++) {
              if( angular.equals(node, nuList.$src[i]) ) {
                return i;
              }
            }
            return -1;
          };

          this.$add = function(item) {
            if(item) {
              nuList.$src.push(item);
            }
          };

          this.$remove = function(node) {
            nuList.$src.splice(nuList.$indexOf(node), 1);
          };

          this.$empty = function() {
            $element.empty();
          };

          this.$draw = function() {
            nuList.$empty();
            angular.forEach(nuList.$src, function(item) {
              if( nu.isDefinedAndNotNull(item) ) {
                render(item);
              }
            });
          };
        }],
        link: function(scope, element, attrs, nuList) {
          var src = attrs[attrs.nuList? 'nuList' : 'src'];
          scope.$watchCollection(src, function(value) {
            nuList.$src = value? value : [];
            nuList.$draw();
          });
        }
      };
    }
  ]);

  list.directive('nuListType', [
    function() {
      var nodes = {
        'img': angular.element(''),
        'txt': angular.element('')
      };

      var engines = {
        'img': function(node) {
          return function(value) {
            node.removeClass('async').find('img')
              .attr('src', value);
          };
        },
        'txt': function(node) {
          return function(value) {
            node.removeClass('async').text(value);
          };
        }
      };

      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var engine, baseNode;
          nuList.$formatters = [];

          attr.$observe('nuListType', function(value) {
            var isIMG = value == 'img';
            engine = engines[(isIMG)? 'img' : 'txt'];
            baseNode = nodes[(isIMG)? 'img' : 'txt'];
          });

          nuList.$render = function(item) {
            //TODO: Node Pooling
            var node = baseNode.clone();
            nu.pipeLine(nuList.$formatters, engine(node))
              .onAsync(function(){
                node.addClass('async');
              }).next(item);
            nuList.$render.append(node);
            return node;
          };
          nuList.$render.append = function(node) {
            element.append(node); // angular.element(element[0])
          };
        }
      };
    }
  ]);

  list.directive('nuListRemovable', [
    function() { // ClickToRemove
      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var canRemove, remove_event = function(event) {
            nuList.$remove(target.data('src'));
            scope.$digest();
          };

          nuList.$link = function(node) {
            if(canRemove === false) { return; }
            node.addClass('remove').on('click', remove_event);
          };

          var updateView = function() {
            var nodes = element.find('span');
            if(canRemove) {
              nodes.addClass('remove').on('click', remove_event);
              return;
            }
            nodes.removeClass('remove').off('click');
          };

          attr.$observe('nuListRemovable', function(value) {
            canRemove = value === 'false'? false: true;
            updateView();
          });
        }
      };
    }
  ]);

  list.directive('nuListAddable', [
    function() { // ClickToRemove
      var linkers = {
        'img' : function(scope, element, attr, nuList) {
          var buffer = angular.element('' +
            '<input type="file">');
          var input = buffer.find('input');
          input.on('change', function(event) {
            for(var i = 0; i < event.currentTarget.files.length; i++) {
              nuList.$add(event.currentTarget.files[i]);
              scope.$digest();
            }
          });
          attr.$observe('multiple', function(value) {
            if(angular.isDefined(value) && value) { input.attr('multiple',''); }
              else { input.removeAttr('multiple'); }
          });

          //buffer.doFocus = angular.noop;
          buffer.doFocus = function(event) {
            if(event.srcElement === element[0]) {
              buffer[0].click();
            }
          };

          return buffer;
        },
        'txt' : function(scope, element, attr, nuList) {
          var buffer = angular.element(' ');

          buffer.on('keydown', function(event) {
            var keyCode = (event.which || event.keyCode);
            if (keyCode === 13) {
              var input = this.innerHTML.replace(' ','').trim();
              this.innerHTML = '';
              //this.blur();
              event.preventDefault();
              if (input !== '') {
                if (input) {
                  nuList.$add(input);
                  scope.$digest();
                }
              }
            }
          }).on('focus', function() {
            this.innerHTML = this.innerHTML.replace(' ', '');
          }).on('blur', function() { // event
            if(this.innerHTML === '') { this.innerHTML = ' '; }
          });

          buffer.doFocus = function(event) {
            event.stopPropagation();
            buffer[0].focus();
          };

          return buffer;
        }
      };

      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var buffer, elementRaw = element[0], hasBuffer, base$add = nuList.$add;
          nuList.$parsers = [];
          nuList.$add = function(item) {
            nu.pipeLine(nuList.$parsers, base$add).next(item);
          };

          var nuList$empty = nuList.$empty;
          var empty = function() {
            while(elementRaw.firstChild != elementRaw.lastChild) {
              angular.element(elementRaw.firstChild).remove();
            }
          };

          var nuList$render_append = nuList.$render.append;
          var append = function(node) {
            elementRaw.insertBefore(node[0], buffer[0]);
          };

          var picture_push = function() {
            this.done(this.result);
          };

          var picture_formatter = function(value) {
            if(value.name && value.type && value.type.match(/image.*/)) {
              var reader = new FileReader();
              reader.done = this.async();
              reader.onload = picture_push;
              reader.readAsDataURL(value);
            }
            return value;
          };

          var updateBuffer = function() {
            element.off('mouseup');
            if(buffer) {
              if( !hasBuffer && buffer[0].parentNode === element[0]) {
                element[0].removeChild(buffer[0]);
                nuList.$empty = nuList$empty;
                nuList.$render.append = nuList$render_append;
                return;
              }

              element.append(buffer);
              nuList.$empty = empty;
              nuList.$render.append = append;
              element.on('mouseup', buffer.doFocus);
            }
          };

          attr.$observe('nuListAddable', function(value) {
            hasBuffer = value !== 'false'? true: false;
            updateBuffer();
          });

          attr.$observe('nuListType', function(value) {
            var isIMG = value == 'img';
            var get_buffer = linkers[isIMG? 'img' : 'txt'];
            if(buffer) {
              if(buffer[0].parentNode === element[0]) {
                buffer.remove();
              }
              buffer.unbind();
            }

            buffer = get_buffer(scope, element, attr, nuList);
            updateBuffer();

            if(isIMG) { // TODO: remove the formater if type changes
              nuList.$formatters.push(picture_formatter);
            }
          });
        }
      };
    }
  ]);

  list.directive('nuListTypeFilter', [
    function() { // ClickToRemove
      return {
        restrict: 'A',
        require: 'nuList', // nuListAddable
        link: function(scope, element, attr, nuList) {
          var type;
          nuList.$parsers.push(function(file){
            if( !nu.isDefinedAndNotNull(type) ||
                    file.type.match(type) ) {
              return file;
            }
          });

          attr.$observe('nuListTypeFilter', function(value) {
            type = new RegExp(value);
          });
        }
      };
    }
  ]);
//TODO: Need to support two events onRemove onAdd
})(angular, nu);
<commit_msg>Update list digest issue<commit_after>/**
 * ngul 0.4
 * Copyright 2013 Kamalakar Gadireddy. and other contributors; https://github.com/gkodes/ngul
 * @license: MIT
 */

(function(angular, nu) {
'use strict';
/*global nu, angular: true, FileReader: true*/
  var list = angular.module('nu.list', []);
  list.directive('nuList', [
    function() { // try to rename it to collection or list
      return {
        template: '

',
        restrict: 'EACM', // 145 550 ? 12118
        replace: true,
        controller: ['$scope', '$element', '$attrs', function($scope, $element) {
          this.$render = angular.noop; // invokde for rending an element, expected an compiler
          this.$filter = angular.noop; // invokde before render if return false wont render that element
          this.$link = angular.noop; // invokde after render with the element

          this.$indexOf = angular.noop;
          var nuList = this;

          var render = function(item) {
            var node = nuList.$render(item);
            node.data('src', item);
            nuList.$link(node);
          };

          this.$indexOf = function(node) {
            for(var i = 0; i < nuList.$src.length; i++) {
              if( angular.equals(node, nuList.$src[i]) ) {
                return i;
              }
            }
            return -1;
          };

          this.$add = function(item) {
            if(item) {
              nuList.$src.push(item);
            }
          };

          this.$remove = function(node) {
            nuList.$src.splice(nuList.$indexOf(node), 1);
          };

          this.$empty = function() {
            $element.empty();
          };

          this.$draw = function() {
            nuList.$empty();
            angular.forEach(nuList.$src, function(item) {
              if( nu.isDefinedAndNotNull(item) ) {
                render(item);
              }
            });
          };
        }],
        link: function(scope, element, attrs, nuList) {
          var src = attrs[attrs.nuList? 'nuList' : 'src'];
          scope.$watchCollection(src, function(value) {
            nuList.$src = value? value : [];
            nuList.$draw();
          });
        }
      };
    }
  ]);

  list.directive('nuListType', [
    function() {
      var nodes = {
        'img': angular.element(''),
        'txt': angular.element('')
      };

      var engines = {
        'img': function(node) {
          return function(value) {
            node.removeClass('async').find('img')
              .attr('src', value);
          };
        },
        'txt': function(node) {
          return function(value) {
            node.removeClass('async').text(value);
          };
        }
      };

      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var engine, baseNode;
          nuList.$formatters = [];

          attr.$observe('nuListType', function(value) {
            var isIMG = value == 'img';
            engine = engines[(isIMG)? 'img' : 'txt'];
            baseNode = nodes[(isIMG)? 'img' : 'txt'];
          });

          nuList.$render = function(item) {
            //TODO: Node Pooling
            var node = baseNode.clone();
            nu.pipeLine(nuList.$formatters, engine(node))
              .onAsync(function(){
                node.addClass('async');
              }).next(item);
            nuList.$render.append(node);
            return node;
          };
          nuList.$render.append = function(node) {
            element.append(node); // angular.element(element[0])
          };
        }
      };
    }
  ]);

  list.directive('nuListRemovable', [
    function() { // ClickToRemove
      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var canRemove, remove_event = function(event) {
            var target = angular.element(event.currentTarget);
            nuList.$remove(target.data('src'));
            scope.$digest();
          };

          nuList.$link = function(node) {
            if(canRemove === false) { return; }
            node.addClass('remove').on('click', remove_event);
          };

          var updateView = function() {
            var nodes = element.find('span');
            if(canRemove) {
              nodes.addClass('remove').on('click', remove_event);
              return;
            }
            nodes.removeClass('remove').off('click');
          };

          attr.$observe('nuListRemovable', function(value) {
            canRemove = value === 'false'? false: true;
            updateView();
          });
        }
      };
    }
  ]);

  list.directive('nuListAddable', [
    function() { // ClickToRemove
      var linkers = {
        'img' : function(scope, element, attr, nuList) {
          var buffer = angular.element('' +
            '<input type="file">');
          var input = buffer.find('input');
          input.on('change', function(event) {
            for(var i = 0; i < event.currentTarget.files.length; i++) {
              nuList.$add(event.currentTarget.files[i]);
              scope.$digest();
            }
          });
          attr.$observe('multiple', function(value) {
            if(angular.isDefined(value) && value) { input.attr('multiple',''); }
              else { input.removeAttr('multiple'); }
          });

          //buffer.doFocus = angular.noop;
          buffer.doFocus = function(event) {
            if(event.srcElement === element[0]) {
              buffer[0].click();
            }
          };

          return buffer;
        },
        'txt' : function(scope, element, attr, nuList) {
          var buffer = angular.element(' ');

          buffer.on('keydown', function(event) {
            var keyCode = (event.which || event.keyCode);
            if (keyCode === 13) {
              var input = this.innerHTML.replace(' ','').trim();
              this.innerHTML = '';
              //this.blur();
              event.preventDefault();
              if (input !== '') {
                if (input) {
                  nuList.$add(input);
                  scope.$digest();
                }
              }
            }
          }).on('focus', function() {
            this.innerHTML = this.innerHTML.replace(' ', '');
          }).on('blur', function() { // event
            if(this.innerHTML === '') { this.innerHTML = ' '; }
          });

          buffer.doFocus = function(event) {
            event.stopPropagation();
            buffer[0].focus();
          };

          return buffer;
        }
      };

      return {
        restrict: 'A',
        require: 'nuList',
        link: function(scope, element, attr, nuList) {
          var buffer, elementRaw = element[0], hasBuffer, base$add = nuList.$add;
          nuList.$parsers = [];
          nuList.$add = function(item) {
            nu.pipeLine(nuList.$parsers, base$add).next(item);
          };

          var nuList$empty = nuList.$empty;
          var empty = function() {
            while(elementRaw.firstChild != elementRaw.lastChild) {
              angular.element(elementRaw.firstChild).remove();
            }
          };

          var nuList$render_append = nuList.$render.append;
          var append = function(node) {
            elementRaw.insertBefore(node[0], buffer[0]);
          };

          var picture_push = function() {
            this.done(this.result);
          };

          var picture_formatter = function(value) {
            if(value.name && value.type && value.type.match(/image.*/)) {
              var reader = new FileReader();
              reader.done = this.async();
              reader.onload = picture_push;
              reader.readAsDataURL(value);
            }
            return value;
          };

          var updateBuffer = function() {
            element.off('mouseup');
            if(buffer) {
              if( !hasBuffer && buffer[0].parentNode === element[0]) {
                element[0].removeChild(buffer[0]);
                nuList.$empty = nuList$empty;
                nuList.$render.append = nuList$render_append;
                return;
              }

              element.append(buffer);
              nuList.$empty = empty;
              nuList.$render.append = append;
              element.on('mouseup', buffer.doFocus);
            }
          };

          attr.$observe('nuListAddable', function(value) {
            hasBuffer = value !== 'false'? true: false;
            updateBuffer();
          });

          attr.$observe('nuListType', function(value) {
            var isIMG = value == 'img';
            var get_buffer = linkers[isIMG? 'img' : 'txt'];
            if(buffer) {
              if(buffer[0].parentNode === element[0]) {
                buffer.remove();
              }
              buffer.unbind();
            }

            buffer = get_buffer(scope, element, attr, nuList);
            updateBuffer();

            if(isIMG) { // TODO: remove the formater if type changes
              nuList.$formatters.push(picture_formatter);
            }
          });
        }
      };
    }
  ]);

  list.directive('nuListTypeFilter', [
    function() { // ClickToRemove
      return {
        restrict: 'A',
        require: 'nuList', // nuListAddable
        link: function(scope, element, attr, nuList) {
          var type;
          nuList.$parsers.push(function(file){
            if( !nu.isDefinedAndNotNull(type) ||
                    file.type.match(type) ) {
              return file;
            }
          });

          attr.$observe('nuListTypeFilter', function(value) {
            type = new RegExp(value);
          });
        }
      };
    }
  ]);
//TODO: Need to support two events onRemove onAdd
})(angular, nu);
<|endoftext|>


<commit_before>'use strict';

var SP = (function () {

    var player = document.getElementById('player');
    var pause = document.getElementById('pause');
    var play = document.getElementById('play');
    var queue = [];
    var opts = {};
    var clickEvents = ['click', 'onclick'];

    var plugin = {
        config: function (options) {
            //if HTML5 audio is not supported DIE!!!
            var res = typeof (player.play) == 'undefined' ? false : true;
            if (res == false) {
                console.log('HTML5 audio not supported');
                return;
            }
            //end
            opts = {
                playlist: options.playlist,
                autoplay: options.autoplay || false,
                selectors: {
                    playlist: document.getElementById(options.selectors.playlist) || 'document.getElementById("playlist")',
                    art: document.getElementById(options.selectors.art) || 'document.getElementById("album-art")',
                    title: document.getElementById(options.selectors.title) || 'document.getElementById("playing-title")',
                    artist: document.getElementById(options.selectors.artist) || 'document.getElementById("playing-artist")',
                    shuffle: document.getElementById(options.selectors.shuffle) || 'document.getElementById("shuffle-play")'
                }
            }

            plugin.assembleHTML(opts);
        },

        assembleHTML: function (opts) {
            var ul = document.createElement('ul');
            opts.selectors.playlist.appendChild(ul);
            opts.playlist.forEach(function (val, ix) {
                var li = document.createElement('li');
                li.setAttribute('data-src', val.track);
                li.setAttribute('data-queue', ix);
                li.setAttribute('data-art', val.art);
                li.setAttribute('class', 'track');
                queue.push(li);

                /*Add title*/
                var title = document.createElement('p');
                title.setAttribute('class', 'title');
                title.innerHTML = val.title;
                li.appendChild(title)
                /*add title*/

                /*add artist*/
                var artist = document.createElement('span');
                artist.setAttribute('class', 'artist');
                artist.innerHTML = val.artist;
                li.appendChild(artist)
                /*add artist*/

                /*add artist*/
                var album = document.createElement('span');
                album.setAttribute('class', 'album');
                album.innerHTML = val.album;
                li.appendChild(album)
                /*add artist*/

                ul.appendChild(li);
                plugin.attachEvent(li, plugin.playTrack, clickEvents);

                //post proc
                opts.autoplay == true ? plugin.playTrack(ul.getElementsByTagName('li')[0]) : ''; //first load
                plugin.attachEvent(opts.selectors.shuffle, plugin.shuffle, clickEvents);
                plugin.attachEvent(document.getElementById('prev'), plugin.prevTrack, clickEvents);
                plugin.attachEvent(document.getElementById('next'), plugin.nextTrack, clickEvents);
            });
        },

        attachEvent: function (el, func, arr) {
            var e1 = arr[0]; //event1
            var e2 = arr[1]; //event2
            el[window.addEventListener ? 'addEventListener' : 'attachEvent'](window.addEventListener ? e1 : e2, func, false);
        },

        playTrack: function (elem) {
            var item = elem.target ? elem.target.nodeName == 'LI' ? elem.target : elem.target.parentNode : elem;
            player.setAttribute('src', item.getAttribute('data-src'));
            plugin.removeClass();
            plugin.addClass(item, 'active');
            plugin.updatePlaying(item);
            plugin.play();
            plugin.attachEvent(pause, plugin.pause, clickEvents);
            plugin.attachEvent(play, plugin.play, clickEvents);
            plugin.queue(item.getAttribute('data-queue'));
            opts.selectors.art.style.backgroundImage = "url('" + item.getAttribute('data-art') + "')";
        },

        updatePlaying: function (current) {
            var title = current.getElementsByClassName('title')[0].innerHTML;
            var artist = current.getElementsByClassName('artist')[0].innerHTML;
            opts.selectors.title.innerHTML = title;
            opts.selectors.artist.innerHTML = artist;
        },

        play: function () {
            player.play();
            pause.style = 'display:block';
            play.style = 'display:none';
        },

        pause: function () {
            player.pause();
            play.style = 'display:block';
            pause.style = 'display:none';
        },

        queue: function (i) {
            var n = Number(i) + 1;
            var elem = document.getElementsByClassName('track')[n];
            if (elem == null) {
                elem = document.getElementsByClassName('track')[0];
            }
            player.onended = function () {
                plugin.nextSong(elem);
            }
        },

        shuffle: function () {
            var randIndx = (Math.random() * (queue.length - 0) + 0).toFixed(0); //generate a valid random indx
            var elem = queue[randIndx];
            plugin.playTrack(elem);
        },

        nextSong: function (elem) {
            plugin.playTrack(elem);
        },

        nextTrack: function () {
            var current = document.getElementsByClassName('active')[0].getAttribute('data-queue');
            var n = Number(current) + 1;
            var elem = document.getElementsByClassName('track')[n];
            if (elem == null) {
                elem = document.getElementsByClassName('track')[0];
            }
            plugin.playTrack(elem);
        },

        prevTrack: function () {
            var current = document.getElementsByClassName('active')[0].getAttribute('data-queue');
            var n = Number(current) - 1;
            var elem = n >= 0 ? document.getElementsByClassName('track')[n] : document.getElementsByClassName('track')[queue.length - 1];
            plugin.playTrack(elem);
        },

        addClass: function (elem, value) {
            elem.className += ' ' + value;
        },

        removeClass: function () {
            var ul = opts.selectors.playlist.getElementsByTagName('ul')[0];
            var li = ul.getElementsByClassName('active');
            if (li.length > 0) {
                li[0].className = 'track';
            }
        }
    }

    //return the plugin
    return plugin;

})();
<commit_msg>style declaration fixes<commit_after>'use strict';

var SP = (function () {

    var player = document.getElementById('player');
    var pause = document.getElementById('pause');
    var play = document.getElementById('play');
    var queue = [];
    var opts = {};
    var clickEvents = ['click', 'onclick'];

    var plugin = {
        config: function (options) {
            //if HTML5 audio is not supported DIE!!!
            var res = typeof (player.play) == 'undefined' ? false : true;
            if (res == false) {
                console.log('HTML5 audio not supported');
                return;
            }
            //end
            opts = {
                playlist: options.playlist,
                autoplay: options.autoplay || false,
                selectors: {
                    playlist: document.getElementById(options.selectors.playlist) || 'document.getElementById("playlist")',
                    art: document.getElementById(options.selectors.art) || 'document.getElementById("album-art")',
                    title: document.getElementById(options.selectors.title) || 'document.getElementById("playing-title")',
                    artist: document.getElementById(options.selectors.artist) || 'document.getElementById("playing-artist")',
                    shuffle: document.getElementById(options.selectors.shuffle) || 'document.getElementById("shuffle-play")'
                }
            }

            plugin.assembleHTML(opts);
        },

        assembleHTML: function (opts) {
            var ul = document.createElement('ul');
            opts.selectors.playlist.appendChild(ul);
            opts.playlist.forEach(function (val, ix) {
                var li = document.createElement('li');
                li.setAttribute('data-src', val.track);
                li.setAttribute('data-queue', ix);
                li.setAttribute('data-art', val.art);
                li.setAttribute('class', 'track');
                queue.push(li);

                /*Add title*/
                var title = document.createElement('p');
                title.setAttribute('class', 'title');
                title.innerHTML = val.title;
                li.appendChild(title)
                /*add title*/

                /*add artist*/
                var artist = document.createElement('span');
                artist.setAttribute('class', 'artist');
                artist.innerHTML = val.artist;
                li.appendChild(artist)
                /*add artist*/

                /*add artist*/
                var album = document.createElement('span');
                album.setAttribute('class', 'album');
                album.innerHTML = val.album;
                li.appendChild(album)
                /*add artist*/

                ul.appendChild(li);
                plugin.attachEvent(li, plugin.playTrack, clickEvents);

                //post proc
                opts.autoplay == true ? plugin.playTrack(ul.getElementsByTagName('li')[0]) : ''; //first load
                plugin.attachEvent(opts.selectors.shuffle, plugin.shuffle, clickEvents);
                plugin.attachEvent(document.getElementById('prev'), plugin.prevTrack, clickEvents);
                plugin.attachEvent(document.getElementById('next'), plugin.nextTrack, clickEvents);
            });
        },

        attachEvent: function (el, func, arr) {
            var e1 = arr[0]; //event1
            var e2 = arr[1]; //event2
            el[window.addEventListener ? 'addEventListener' : 'attachEvent'](window.addEventListener ? e1 : e2, func, false);
        },

        playTrack: function (elem) {
            var item = elem.target ? elem.target.nodeName == 'LI' ? elem.target : elem.target.parentNode : elem;
            player.setAttribute('src', item.getAttribute('data-src'));
            plugin.removeClass();
            plugin.addClass(item, 'active');
            plugin.updatePlaying(item);
            plugin.play();
            plugin.attachEvent(pause, plugin.pause, clickEvents);
            plugin.attachEvent(play, plugin.play, clickEvents);
            plugin.queue(item.getAttribute('data-queue'));
            var albumart = 'background:' + "url('" + item.getAttribute('data-art') + "')";
            opts.selectors.art.setAttribute('style', albumart);
        },

        updatePlaying: function (current) {
            var title = current.getElementsByClassName('title')[0].innerHTML;
            var artist = current.getElementsByClassName('artist')[0].innerHTML;
            opts.selectors.title.innerHTML = title;
            opts.selectors.artist.innerHTML = artist;
        },

        play: function () {
            player.play();
            pause.setAttribute('style', 'display:block');
            play.setAttribute('style', 'display:none');
        },

        pause: function () {
            player.pause();
            play.setAttribute('style', 'display:block');
            pause.setAttribute('style' ,'display:none');
        },

        queue: function (i) {
            var n = Number(i) + 1;
            var elem = document.getElementsByClassName('track')[n];
            if (elem == null) {
                elem = document.getElementsByClassName('track')[0];
            }
            player.onended = function () {
                plugin.nextSong(elem);
            }
        },

        shuffle: function () {
            var randIndx = (Math.random() * (queue.length - 0) + 0).toFixed(0); //generate a valid random indx
            var elem = queue[randIndx];
            plugin.playTrack(elem);
        },

        nextSong: function (elem) {
            plugin.playTrack(elem);
        },

        nextTrack: function () {
            var current = document.getElementsByClassName('active')[0].getAttribute('data-queue');
            var n = Number(current) + 1;
            var elem = document.getElementsByClassName('track')[n];
            if (elem == null) {
                elem = document.getElementsByClassName('track')[0];
            }
            plugin.playTrack(elem);
        },

        prevTrack: function () {
            var current = document.getElementsByClassName('active')[0].getAttribute('data-queue');
            var n = Number(current) - 1;
            var elem = n >= 0 ? document.getElementsByClassName('track')[n] : document.getElementsByClassName('track')[queue.length - 1];
            plugin.playTrack(elem);
        },

        addClass: function (elem, value) {
            elem.className += ' ' + value;
        },

        removeClass: function () {
            var ul = opts.selectors.playlist.getElementsByTagName('ul')[0];
            var li = ul.getElementsByClassName('active');
            if (li.length > 0) {
                li[0].className = 'track';
            }
        }
    }

    //return the plugin
    return plugin;

})();
<|endoftext|>


<commit_before>// for debugging and tweaking from the console
var MAPS = {};
(function() {

    // returns the map provider for a given TileStache layer name
    function getProvider(layer) {
        return new MM.StamenTileLayer(layer);
    }

    function onImageError(_map, img) {
        // img.src = "images/tile-404.gif";
    }

    function init() {

        var providerLabel = document.getElementById("current-provider"),
            currentProvider = "toner",
            mapsByProvider = MAPS.byProvider = {};

        // our main map
        var main = MAPS.main = new MM.Map("map-main", getProvider(currentProvider), null,
            [new MM.DragHandler(), new MM.DoubleClickHandler(), new MM.TouchHandler()]);
        main.layers[0].requestManager.addCallback("requesterror", onImageError);

        mapsByProvider[currentProvider] = main;

        // keep a reference to the sub-map wrapper to figure out
        // positioning stuff
        var wrapper = MAPS.wrapper = document.getElementById("maps-sub"),
            subs = MAPS.sub = [],
            // then grab all the sub-map element references
            subParents = wrapper.querySelectorAll(".map");
        // create a map for each sub-map element
        for (var i = 0; i < subParents.length; i++) {
            var el = subParents[i],
                // the provider is based on the data-provider HTML attribute
                provider = el.getAttribute("data-provider"),
                // FIXME: these maps are not interactive
                map = new MM.Map(el, getProvider(provider), null, [new MM.DragHandler()]);
            map.addCallback("panned", function(_map, offset) {
                if (!main.panning) {
                    _map.panning = true;
                    main.panBy(offset[0], offset[1]);
                    _map.panning = false;
                }
            });
            map.layers[0].requestManager.addCallback("requesterror", onImageError);
            mapsByProvider[provider] = map;
            subs.push(map);
        }

        // sync sub-maps to the main map's center using their
        // relative positions on screen
        function updateSubMaps() {
            var mainWidth = main.dimensions.x,
                wrapperWidth = wrapper.offsetWidth,
                wrapperTop = wrapper.offsetTop,
                offsetX = mainWidth - (mainWidth - wrapperWidth) / 2;
            for (var i = 0; i < subs.length; i++) {
                var sub = subs[i],
                    point = new MM.Point(0, 0);
                point.x = offsetX - sub.dimensions.x / 2;
                point.y = wrapperTop + sub.parent.offsetTop + sub.dimensions.y / 2;
                sub.setCenterZoom(main.pointLocation(point), main.getZoom());
            }
        }

        // zoom click handlers
        MM.addEvent(document.getElementById("zoom-in"), "click", function() {
            try { main.zoomIn(); } catch (e) { }
            return false;
        });
        MM.addEvent(document.getElementById("zoom-out"), "click", function() {
            try { main.zoomOut(); } catch (e) { }
            return false;
        });

        var fslink = document.getElementById("fullscreen");
        if (fslink) {
            var fullscreen = false,
                fstimeout;
            function toggleFullscreen(link) {
                fullscreen = !fullscreen;
                if (fullscreen) {
                    document.body.className = "fullscreen";
                } else {
                    document.body.className = null;
                }
                clearTimeout(fstimeout);
                fstimeout = setTimeout(main.windowResize(), 1000);
            }

            MM.addEvent(fslink, "click", function(e) {
                try {
                    toggleFullscreen(e.target);
                } catch (error) {
                    console.error(error);
                }
                return MM.cancelEvent(e);
            });

            MM.addEvent(window, "keyup", function(e) {
                if (fullscreen && e.keyCode == 27) { // escape
                    toggleFullscreen(e.target);
                }
            });
        }

        // pan the sub-maps when the main map is panned
        main.addCallback("panned", function(_map, offset) {
            if (main.panning) return;
            main.panning = true;
            for (var i = 0; i < subs.length; i++) {
                var sub = subs[i];
                if (!sub.panning) {
                    sub.panBy(offset[0], offset[1]);
                }
            }
            main.panning = false;
        });

        // and for all other map redraw events, re-sync them
        main.addCallback("zoomed", updateSubMaps);
        main.addCallback("extentset", updateSubMaps);
        main.addCallback("centered", updateSubMaps);

        // set the initial map position
        main.setCenterZoom(new MM.Location(37.7706, -122.3782), 12);

        function updateTitle(map, provider) {
            // update the link in the clicked sub-map
            var node = map.parent.querySelector(".provider-name");
            node.innerHTML = provider.substr(0, 1).toUpperCase() + provider.substr(1);
            if ("href" in node) {
                node.href = "#" + provider;
            }
        }

        // and set up listening for the browser's location hash
        var hasher = new ProviderHash(main, currentProvider, function(provider) {
            if (!provider || !(provider in mapsByProvider)) {
                return false;
            }
            // if the provider has changed...
            if (provider != currentProvider) {
                // grab the provider from the corresponding map
                var source = mapsByProvider[provider],
                    target = main;
                // swap layers
                source.setLayerAt(0, getProvider(currentProvider));
                target.setLayerAt(0, getProvider(provider));

                updateTitle(source, currentProvider);
                updateTitle(target, provider);

                // update the selected provider label text
                if (providerLabel) {
                    providerLabel.innerHTML = provider;
                }

                // swap the map references in mapsByProvider
                mapsByProvider[provider] = target;
                mapsByProvider[currentProvider] = source;
                // and, finally, update currentProvider
                currentProvider = provider;
            }
            return true;
        });

        // set up form element references
        var searchForm = document.getElementById("search"),
            searchInput = document.getElementById("search-location"),
            searchButton = document.getElementById("search-submit");
        // listen for the submit event
        MM.addEvent(searchForm, "submit", function(e) {
            // remember the old search text
            var oldSearchText = searchButton.getAttribute("value");
            // put the button into its submitting state
            searchButton.setAttribute("value", "Finding...");
            searchButton.setAttribute("class", "btn disabled");
            // set up a function to rever the form to its original state
            // (which executes whether there was an error or not)
            function revert() {
                searchButton.setAttribute("class", "btn");
                searchButton.setAttribute("value", oldSearchText);
            }

            var query = searchInput.value;
            YahooPlaceSearch.geocode(query, function(places) {
                revert();
                // console.log("search results:", results);
                // TODO: find the most relevant result?
                try {
                    var result = places.place[0],
                        northeast = result.boundingBox.northEast,
                        southwest = result.boundingBox.southWest;
                    main.setExtent([
                        new MM.Location(northeast.latitude, northeast.longitude),
                        new MM.Location(southwest.latitude, southwest.longitude)
                    ]);
                } catch (e) {
                    alert('Sorry, something went wrong when searching for "' + query + '".');
                }
                // main.panBy(-(main.dimensions.x - wrapper.offsetWidth) / 2, 0);
            }, function(error) {
                revert();
                alert('Sorry, we couldn\'t find "' + query + '".');
            });

            // cancel the submit event
            return MM.cancelEvent(e);
        });

        // create static mini-maps for each of these elements
        var minis = document.querySelectorAll("#content .map");
        MAPS.minis = [];
        for (var i = 0; i < minis.length; i++) {
            var el = minis[i],
                provider = getProvider(el.getAttribute("data-provider")),
                center = parseCenter(el.getAttribute("data-center")),
                zoom = parseInt(el.getAttribute("data-zoom")),
                map = new MM.Map(el, provider, null, []);
            map.setCenterZoom(center, zoom);
            MAPS.minis.push(map);
        }

        var inheritLinks = document.querySelectorAll("a.hashish");
        for (var i = 0; i < inheritLinks.length; i++) {
            MM.addEvent(inheritLinks[i], "mouseover", function(e) {
                var link = e.target,
                    parts = link.href.split("#"),
                    suffix = location.hash.split("/").slice(1).join("/");
                link.href = [parts[0], suffix].join("#");
            });
        }
    }

    // parse a string into an MM.Location instance
    function parseCenter(str) {
        var parts = str.split(/,\s*/),
            lat = parseFloat(parts[0]),
            lon = parseFloat(parts[1]);
        return new MM.Location(lat, lon);
    }

    /**
     * The ProviderHash is a class that looks for a provider name at the beginning
     * of the hash and calls the supplied setProvider(provider) function whenever it
     * changes.
     *
     * One feature of this parser is that it substitutes the center and zoom back in
     * if the hash changes to just "#provider", so you can link to new providers by
     * setting a link's href to simply "#provider" and ProviderHash will update the
     * hash accordingly.
     *
     * setProvider(provider) should accept a string and return true if the supplied
     * provider name was valid, or return false in any other case.
     *
     * Note also that ProviderHash requires a valid providerName in the constructor
     * to correctly set the initial hash value.
     */
    var ProviderHash = function(map, providerName, setProvider) {
        this.providerName = providerName;
        this.setProvider = setProvider;
        MM.Hash.call(this, map);
    };

    ProviderHash.prototype = {
        // the currently selected provider name
        providerName: null,

        /**
         * Our parseHash() function looks for a provider name in the beginning of
         * the URL.
         */
        parseHash: function(hash) {
            var parts = hash.split("/");
            if (parts.length > 0) {
                var provider = parts.shift();
                var parsed = parts.length
                    ? MM.Hash.prototype.parseHash.call(this, parts.join("/"))
                    : {center: this.map.getCenter(), zoom: this.map.getZoom()};
                if (parsed) {
                    // console.log("parsed hash:", provider, parsed);
                    var didSetProvider = this.setProvider.call(this.map, provider);
                    if (didSetProvider) {
                        this.providerName = provider;
                        return parsed;
                    } else {
                        return false;
                    }
                } else {
                    // console.log("parse error:", hash, parts, this.providerName);
                }
                return parsed;
            } else {
                // console.warn("(zero length, unable to parse");
                return false;
            }
        },

        /**
         * Our formatHash() function inserts the provider name as the first
         * slash-delimited element in the URL.
         */
        formatHash: function(hash) {
            var format = MM.Hash.prototype.formatHash.call(this, hash);
            return "#" + this.providerName + "/" + format.substr(1);
        }
    };

    MM.extend(ProviderHash, MM.Hash);

    try {

        init();

    } catch (e) {
        console.error(e);
    }

})();

var YahooPlaceSearch = {
    appid: "1DiQEyLV34HbAVHyl0iWC5tAZ8wpLMPzIeFE9QsTukhx6H.Cn9bM70c_5dYgh7cR8w--",
    url: "http://where.yahooapis.com/v1/places.q({q});count=1?callback=?",
    geocode: function(query, success, error) {
        var data = {};
        data.appid = YahooPlaceSearch.appid;
        data.select = "long";
        data.format = "json";
        return reqwest({
            url: YahooPlaceSearch.url.replace("{q}", encodeURIComponent(query)),
            type: "jsonp",
            jsonpCallback: "callback",
            data: data,
            success: function(response) {
                var results = response.places;
                if (results) {
                    success.call(null, results);
                } else {
                    error.call(null, "No results", response);
                }
            },
            error: error
        });
    }
};

// quick and dirty MQ search API
var MapQuest = {
    // XXX: this is a Slow Tusnami key registered on the shawn@stamen.com
    // MapQuest developer account
    key: decodeURIComponent("Fmjtd%7Cluua216ynl%2Cbg%3Do5-h4rxg"),
    geocode: function(query, success, error) {
        var data;
        if (typeof query === "string") {
            data = {location: query};
        } else {
            data = query;
        }
        data.inFormat = "kvp";
        data.thumbMaps = false;
        data.key = MapQuest.key;
        data.outFormat = "json";
        return reqwest({
            url: "http://www.mapquestapi.com/geocoding/v1/address?callback=?",
            type: "jsonp",
            jsonpCallback: "callback",
            data: data,
            success: function(response) {
                var results = response.results;
                if (results && results.length) {
                    success.call(null, results);
                } else {
                    error.call(null, "No results");
                }
            },
            error: error
        });
    }
};
<commit_msg>ditch the MapQuest place search interface<commit_after>// for debugging and tweaking from the console
var MAPS = {};
(function() {

    // returns the map provider for a given TileStache layer name
    function getProvider(layer) {
        return new MM.StamenTileLayer(layer);
    }

    function onImageError(_map, img) {
        // img.src = "images/tile-404.gif";
    }

    function init() {

        var providerLabel = document.getElementById("current-provider"),
            currentProvider = "toner",
            mapsByProvider = MAPS.byProvider = {};

        // our main map
        var main = MAPS.main = new MM.Map("map-main", getProvider(currentProvider), null,
            [new MM.DragHandler(), new MM.DoubleClickHandler(), new MM.TouchHandler()]);
        main.layers[0].requestManager.addCallback("requesterror", onImageError);

        mapsByProvider[currentProvider] = main;

        // keep a reference to the sub-map wrapper to figure out
        // positioning stuff
        var wrapper = MAPS.wrapper = document.getElementById("maps-sub"),
            subs = MAPS.sub = [],
            // then grab all the sub-map element references
            subParents = wrapper.querySelectorAll(".map");
        // create a map for each sub-map element
        for (var i = 0; i < subParents.length; i++) {
            var el = subParents[i],
                // the provider is based on the data-provider HTML attribute
                provider = el.getAttribute("data-provider"),
                // FIXME: these maps are not interactive
                map = new MM.Map(el, getProvider(provider), null, [new MM.DragHandler()]);
            map.addCallback("panned", function(_map, offset) {
                if (!main.panning) {
                    _map.panning = true;
                    main.panBy(offset[0], offset[1]);
                    _map.panning = false;
                }
            });
            map.layers[0].requestManager.addCallback("requesterror", onImageError);
            mapsByProvider[provider] = map;
            subs.push(map);
        }

        // sync sub-maps to the main map's center using their
        // relative positions on screen
        function updateSubMaps() {
            var mainWidth = main.dimensions.x,
                wrapperWidth = wrapper.offsetWidth,
                wrapperTop = wrapper.offsetTop,
                offsetX = mainWidth - (mainWidth - wrapperWidth) / 2;
            for (var i = 0; i < subs.length; i++) {
                var sub = subs[i],
                    point = new MM.Point(0, 0);
                point.x = offsetX - sub.dimensions.x / 2;
                point.y = wrapperTop + sub.parent.offsetTop + sub.dimensions.y / 2;
                sub.setCenterZoom(main.pointLocation(point), main.getZoom());
            }
        }

        // zoom click handlers
        MM.addEvent(document.getElementById("zoom-in"), "click", function() {
            try { main.zoomIn(); } catch (e) { }
            return false;
        });
        MM.addEvent(document.getElementById("zoom-out"), "click", function() {
            try { main.zoomOut(); } catch (e) { }
            return false;
        });

        var fslink = document.getElementById("fullscreen");
        if (fslink) {
            var fullscreen = false,
                fstimeout;
            function toggleFullscreen(link) {
                fullscreen = !fullscreen;
                if (fullscreen) {
                    document.body.className = "fullscreen";
                } else {
                    document.body.className = null;
                }
                clearTimeout(fstimeout);
                fstimeout = setTimeout(main.windowResize(), 1000);
            }

            MM.addEvent(fslink, "click", function(e) {
                try {
                    toggleFullscreen(e.target);
                } catch (error) {
                    console.error(error);
                }
                return MM.cancelEvent(e);
            });

            MM.addEvent(window, "keyup", function(e) {
                if (fullscreen && e.keyCode == 27) { // escape
                    toggleFullscreen(e.target);
                }
            });
        }

        // pan the sub-maps when the main map is panned
        main.addCallback("panned", function(_map, offset) {
            if (main.panning) return;
            main.panning = true;
            for (var i = 0; i < subs.length; i++) {
                var sub = subs[i];
                if (!sub.panning) {
                    sub.panBy(offset[0], offset[1]);
                }
            }
            main.panning = false;
        });

        // and for all other map redraw events, re-sync them
        main.addCallback("zoomed", updateSubMaps);
        main.addCallback("extentset", updateSubMaps);
        main.addCallback("centered", updateSubMaps);

        // set the initial map position
        main.setCenterZoom(new MM.Location(37.7706, -122.3782), 12);

        function updateTitle(map, provider) {
            // update the link in the clicked sub-map
            var node = map.parent.querySelector(".provider-name");
            node.innerHTML = provider.substr(0, 1).toUpperCase() + provider.substr(1);
            if ("href" in node) {
                node.href = "#" + provider;
            }
        }

        // and set up listening for the browser's location hash
        var hasher = new ProviderHash(main, currentProvider, function(provider) {
            if (!provider || !(provider in mapsByProvider)) {
                return false;
            }
            // if the provider has changed...
            if (provider != currentProvider) {
                // grab the provider from the corresponding map
                var source = mapsByProvider[provider],
                    target = main;
                // swap layers
                source.setLayerAt(0, getProvider(currentProvider));
                target.setLayerAt(0, getProvider(provider));

                updateTitle(source, currentProvider);
                updateTitle(target, provider);

                // update the selected provider label text
                if (providerLabel) {
                    providerLabel.innerHTML = provider;
                }

                // swap the map references in mapsByProvider
                mapsByProvider[provider] = target;
                mapsByProvider[currentProvider] = source;
                // and, finally, update currentProvider
                currentProvider = provider;
            }
            return true;
        });

        // set up form element references
        var searchForm = document.getElementById("search"),
            searchInput = document.getElementById("search-location"),
            searchButton = document.getElementById("search-submit");
        // listen for the submit event
        MM.addEvent(searchForm, "submit", function(e) {
            // remember the old search text
            var oldSearchText = searchButton.getAttribute("value");
            // put the button into its submitting state
            searchButton.setAttribute("value", "Finding...");
            searchButton.setAttribute("class", "btn disabled");
            // set up a function to rever the form to its original state
            // (which executes whether there was an error or not)
            function revert() {
                searchButton.setAttribute("class", "btn");
                searchButton.setAttribute("value", oldSearchText);
            }

            var query = searchInput.value;
            YahooPlaceSearch.geocode(query, function(places) {
                revert();
                // console.log("search results:", results);
                // TODO: find the most relevant result?
                try {
                    var result = places.place[0],
                        northeast = result.boundingBox.northEast,
                        southwest = result.boundingBox.southWest;
                    main.setExtent([
                        new MM.Location(northeast.latitude, northeast.longitude),
                        new MM.Location(southwest.latitude, southwest.longitude)
                    ]);
                } catch (e) {
                    alert('Sorry, something went wrong when searching for "' + query + '".');
                }
                // main.panBy(-(main.dimensions.x - wrapper.offsetWidth) / 2, 0);
            }, function(error) {
                revert();
                alert('Sorry, we couldn\'t find "' + query + '".');
            });

            // cancel the submit event
            return MM.cancelEvent(e);
        });

        // create static mini-maps for each of these elements
        var minis = document.querySelectorAll("#content .map");
        MAPS.minis = [];
        for (var i = 0; i < minis.length; i++) {
            var el = minis[i],
                provider = getProvider(el.getAttribute("data-provider")),
                center = parseCenter(el.getAttribute("data-center")),
                zoom = parseInt(el.getAttribute("data-zoom")),
                map = new MM.Map(el, provider, null, []);
            map.setCenterZoom(center, zoom);
            MAPS.minis.push(map);
        }

        var inheritLinks = document.querySelectorAll("a.hashish");
        for (var i = 0; i < inheritLinks.length; i++) {
            MM.addEvent(inheritLinks[i], "mouseover", function(e) {
                var link = e.target,
                    parts = link.href.split("#"),
                    suffix = location.hash.split("/").slice(1).join("/");
                link.href = [parts[0], suffix].join("#");
            });
        }
    }

    // parse a string into an MM.Location instance
    function parseCenter(str) {
        var parts = str.split(/,\s*/),
            lat = parseFloat(parts[0]),
            lon = parseFloat(parts[1]);
        return new MM.Location(lat, lon);
    }

    /**
     * The ProviderHash is a class that looks for a provider name at the beginning
     * of the hash and calls the supplied setProvider(provider) function whenever it
     * changes.
     *
     * One feature of this parser is that it substitutes the center and zoom back in
     * if the hash changes to just "#provider", so you can link to new providers by
     * setting a link's href to simply "#provider" and ProviderHash will update the
     * hash accordingly.
     *
     * setProvider(provider) should accept a string and return true if the supplied
     * provider name was valid, or return false in any other case.
     *
     * Note also that ProviderHash requires a valid providerName in the constructor
     * to correctly set the initial hash value.
     */
    var ProviderHash = function(map, providerName, setProvider) {
        this.providerName = providerName;
        this.setProvider = setProvider;
        MM.Hash.call(this, map);
    };

    ProviderHash.prototype = {
        // the currently selected provider name
        providerName: null,

        /**
         * Our parseHash() function looks for a provider name in the beginning of
         * the URL.
         */
        parseHash: function(hash) {
            var parts = hash.split("/");
            if (parts.length > 0) {
                var provider = parts.shift();
                var parsed = parts.length
                    ? MM.Hash.prototype.parseHash.call(this, parts.join("/"))
                    : {center: this.map.getCenter(), zoom: this.map.getZoom()};
                if (parsed) {
                    // console.log("parsed hash:", provider, parsed);
                    var didSetProvider = this.setProvider.call(this.map, provider);
                    if (didSetProvider) {
                        this.providerName = provider;
                        return parsed;
                    } else {
                        return false;
                    }
                } else {
                    // console.log("parse error:", hash, parts, this.providerName);
                }
                return parsed;
            } else {
                // console.warn("(zero length, unable to parse");
                return false;
            }
        },

        /**
         * Our formatHash() function inserts the provider name as the first
         * slash-delimited element in the URL.
         */
        formatHash: function(hash) {
            var format = MM.Hash.prototype.formatHash.call(this, hash);
            return "#" + this.providerName + "/" + format.substr(1);
        }
    };

    MM.extend(ProviderHash, MM.Hash);

    try {

        init();

    } catch (e) {
        console.error(e);
    }

})();

var YahooPlaceSearch = {
    appid: "1DiQEyLV34HbAVHyl0iWC5tAZ8wpLMPzIeFE9QsTukhx6H.Cn9bM70c_5dYgh7cR8w--",
    url: "http://where.yahooapis.com/v1/places.q({q});count=1?callback=?",
    geocode: function(query, success, error) {
        var data = {};
        data.appid = YahooPlaceSearch.appid;
        data.select = "long";
        data.format = "json";
        return reqwest({
            url: YahooPlaceSearch.url.replace("{q}", encodeURIComponent(query)),
            type: "jsonp",
            jsonpCallback: "callback",
            data: data,
            success: function(response) {
                var results = response.places;
                if (results) {
                    success.call(null, results);
                } else {
                    error.call(null, "No results", response);
                }
            },
            error: error
        });
    }
};
<|endoftext|>


<commit_before>var myGamePiece;
var myObstacles= [];
var mySound;
var myBackground;
var myScore;

function startGame() {
    myBackground = new component(1650, 270, "images/background.jpg", 0, 0, "background");
    myGamePiece = new component(30, 30, "images/bird1.png", 10, 120,"image");
 //   myObstacle  = new component(10, 200, "green", 300, 120);
    mySound = new sound("background","sounds/background.mp3");
    myScore = new component("30px", "Consolas", "black", 280, 40, "text");
    myGameArea.start();
    mySound.play();
}

function component(width, height, color, x, y,type) {
    this.type = type;
    if (type == "image" || type == "background") {
        this.image = new Image();
        this.image.src = color;
    }
    this.width = width;
    this.height = height;
    this.speedX = 0;
    this.speedY = 0;
    this.gravity = 0;
    this.gravitySpeed = 0;
    this.x = x;
    this.y = y;
    this.update = function(){
        ctx = myGameArea.context;
        if (this.type == "text") {
            ctx.font = this.width + " " + this.height;
            ctx.fillStyle = color;
            ctx.fillText(this.text, this.x, this.y);
        } else if(type == "image") {
            ctx.drawImage(this.image, this.x, this.y,this.width, this.height);
        } else if (type == "background") {
             ctx.drawImage(this.image, this.x, this.y,this.width, this.height);
        } else {
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }
    this.newPos = function() {
        this.gravitySpeed += this.gravity;
        this.x += this.speedX;
        this.y += this.speedY + this.gravitySpeed;
        if(this.hitBottom()){
            this.gravitySpeed=0;
            this.gravity = 0;
            this.y = myGameArea.canvas.height - this.height;
        }
        if(this.hitTop()){
            this.gravitySpeed=0;
            this.gravity = 0;
            this.y = 0;
            accelerate(0.05);
        }
    }

    this.hitBottom = function() {
        var rockbottom = myGameArea.canvas.height - this.height;
        if (this.y > rockbottom) {
            this.y = rockbottom;
            return true;
        }
    }
    this.hitTop = function() {
        var rockTop = myGameArea.canvas.height - this.height;
        if (this.y < 0) {
            this.y=0;
            return true;
        }
    }
    //crash
    this.crashWith = function(otherobj) {
        var myleft = this.x;
        var myright = this.x + (this.width);
        var mytop = this.y;
        var mybottom = this.y + (this.height);
        var otherleft = otherobj.x;
        var otherright = otherobj.x + (otherobj.width);
        var othertop = otherobj.y;
        var otherbottom = otherobj.y + (otherobj.height);
        var crash = true;
        if ((mybottom < othertop + 2) ||
               (mytop > otherbottom - 2) ||
               (myright < otherleft + 4) ||
               (myleft > otherright - 4)) {
           crash = false;
        }
        return crash;
    }

}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}
function accelerate(n) {
    if (!myGameArea.interval) {myGameArea.interval = setInterval(updateGameArea, 20);}

    myGamePiece.gravity = n;
}
<commit_msg>update touch and background image<commit_after>var myGamePiece;
var myObstacles= [];
var mySound;
var myBackground;
var myScore;

function startGame() {
    myBackground = new component(1650, 270, "images/background.jpg", 0, 0, "background");
    myGamePiece = new component(30, 30, "images/bird1.png", 10, 120,"image");
 //   myObstacle  = new component(10, 200, "green", 300, 120);
    mySound = new sound("background","sounds/background.mp3");
    myScore = new component("30px", "Consolas", "black", 280, 40, "text");
    myGameArea.start();
    mySound.play();
}

function component(width, height, color, x, y,type) {
    this.type = type;
    if (type == "image" || type == "background") {
        this.image = new Image();
        this.image.src = color;
    }
    this.width = width;
    this.height = height;
    this.speedX = 0;
    this.speedY = 0;
    this.gravity = 0;
    this.gravitySpeed = 0;
    this.x = x;
    this.y = y;
    this.update = function(){
        ctx = myGameArea.context;
        if (this.type == "text") {
            ctx.font = this.width + " " + this.height;
            ctx.fillStyle = color;
            ctx.fillText(this.text, this.x, this.y);
        } else if(type == "image") {
            ctx.drawImage(this.image, this.x, this.y,this.width, this.height);
        } else if (type == "background") {
             ctx.drawImage(this.image, this.x, this.y,this.width, this.height);
        } else {
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }
    this.newPos = function() {
        this.gravitySpeed += this.gravity;
        this.x += this.speedX;
        this.y += this.speedY + this.gravitySpeed;
        if (this.type == "background") {
           // console.log(this.x);
            if (this.x == 480-(this.width)) {
                this.x = 0;
            }
        }
        if(this.hitBottom()){
            this.gravitySpeed=0;
            this.gravity = 0;
            this.y = myGameArea.canvas.height - this.height;
        }
        if(this.hitTop()){
            this.gravitySpeed=0;
            this.gravity = 0;
            this.y = 0;
            accelerate(0.05);
        }
    }

    this.hitBottom = function() {
        var rockbottom = myGameArea.canvas.height - this.height;
        if (this.y > rockbottom) {
            this.y = rockbottom;
            return true;
        }
    }
    this.hitTop = function() {
        var rockTop = myGameArea.canvas.height - this.height;
        if (this.y < 0) {
            this.y=0;
            return true;
        }
    }
    //crash
    this.crashWith = function(otherobj) {
        var myleft = this.x;
        var myright = this.x + (this.width);
        var mytop = this.y;
        var mybottom = this.y + (this.height);
        var otherleft = otherobj.x;
        var otherright = otherobj.x + (otherobj.width);
        var othertop = otherobj.y;
        var otherbottom = otherobj.y + (otherobj.height);
        var crash = true;
        if ((mybottom < othertop + 2) ||
               (mytop > otherbottom - 2) ||
               (myright < otherleft + 4) ||
               (myleft > otherright - 4)) {
           crash = false;
        }
        return crash;
    }

}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}
function accelerate(n) {
    if (!myGameArea.interval) {myGameArea.interval = setInterval(updateGameArea, 20);}

    myGamePiece.gravity = n;
}
<|endoftext|>