<commit_before>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');
var Vector2 = require('vector2');
var ajax = require('ajax');
var KickerAPI = require('kickerapi');

function setupMatchWindow(){
  var matchWindow = new UI.Window({
    fullscreen: true,
    action: {
      up: 'images/action_icon_up.png',
      down: 'images/action_icon_down.png',
      select: 'images/action_icon_reload.png'
    }
  });
  //144 x 168

  matchWindow.ui_elements = {};

  matchWindow.ui_elements.loadingText = new UI.Text({ position: new Vector2(  0 ,  66 ), size: new Vector2(144, 32), font: 'gothic-24-bold', text: 'Loading...', textAlign: 'center' });

  matchWindow.ui_elements.placeholder_images = [];
  matchWindow.ui_elements.placeholder_images[0] = new UI.Image({ position: new Vector2( 0  , 5   ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[1] = new UI.Image({ position: new Vector2( 64 , 5   ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[2] = new UI.Image({ position: new Vector2( 0  , 100 ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[3] = new UI.Image({ position: new Vector2( 64 , 100 ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  _.each(
    matchWindow.ui_elements.placeholder_images,
    function(element, index, list){
      matchWindow.add(element);
    }
  );

  matchWindow.ui_elements.score_rect = new UI.Rect({ position: new Vector2(  37 ,  72 ), size: new Vector2(70, 22), backgroundColor: 'clear', borderColor: 'white' });
  matchWindow.add(matchWindow.ui_elements.score_rect);

  matchWindow.ui_elements.player_names = [];
  matchWindow.ui_elements.player_images = [];

  matchWindow.currentMatchIndex = 0; //start with latest match
  matchWindow.on('click', 'up', function() {
    if(league.matches()) {
      matchWindow.currentMatchIndex--;
      if(matchWindow.currentMatchIndex < 0) { matchWindow.currentMatchIndex = 0 }
      renderMatch(league.matches()[matchWindow.currentMatchIndex]);
    }
  });

  matchWindow.on('click', 'down', function() {
    if(league.matches()) {
      matchWindow.currentMatchIndex++;
      if(matchWindow.currentMatchIndex > league.matches().length) { matchWindow.currentMatchIndex = league.matches().length-1 }
      renderMatch(league.matches()[matchWindow.currentMatchIndex]);
    }
  });

  matchWindow.on('click', 'select', function() {
    loadMatches();
  });

  return matchWindow;
}

function setupRankingWindow(){
  var menu = new UI.Menu({
    sections: [{
      title: 'Ranking',
      items: [{
        title: 'Loading...'
      }]
    }]
  });
  menu.on('select', function(e) {
    console.log('Selected' + e.itemIndex);
    console.log(rankingWindow.active_users[e.itemIndex].id)
    loadUserDetails(rankingWindow.active_users[e.itemIndex].id);
  });
  return menu;
}

function setupUserDetailWindow(){
  var card = new UI.Card({});
  return card;
}

var league = new KickerAPI.League('railslove');
var matchWindow = setupMatchWindow();
var rankingWindow = setupRankingWindow();
var userDetailWindow = setupUserDetailWindow();

function loadMatches(){
  matchWindow.add(matchWindow.ui_elements.loadingText);
  matchWindow.currentMatchIndex = 0;
  matchWindow.show();
  league.loadMatches(function(){
    matchWindow.remove(matchWindow.ui_elements.loadingText);
    renderMatch(league.matches()[0]);
  },
  function(data, status){
    console.log('error loading matches', data, status);
  });
}

function loadRanking(){
  rankingWindow.show();
  league.loadUsers(function(){
    console.log(league.users());
    rankingWindow.active_users = _.filter( league.users(), function(element){ return element.active; } );
    rankingWindow.items(0, _.map( rankingWindow.active_users, function(user) { return { title: user.name, subtitle: user.quote }; }));
  },
  function(data, status){
    console.log('error loading users', data, status);
  });
}

function loadUserDetails(id){
  userDetailWindow.show();
  league.loadUserDetails(id, function(user_details){
    console.log(user_details.name);
    userDetailWindow.prop('subtitle', user_details.quote + '');
    userDetailWindow.prop('title', user_details.name);
    if(is_png(user_details.image)){
      userDetailWindow.prop('icon', user_details.image);
    }
    else{
      userDetailWindow.prop('icon', 'images/default_user.png')
    }
  },
  function(data, status){
    console.log('error loading user', data, status);
  });
}

function renderMenu(){
  var menu = new UI.Menu({
    sections: [{
      title: 'Railslove Kickerapp',
      items: [{
        title: 'Matches',
        subtitle: 'All games'
      }, {
        title: 'Ranking',
        subtitle: 'How do the users rank'
      }]
    }]
  });
  menu.show()
  menu.on('select', function(e) {
    if(e.itemIndex == 0){
      loadMatches();
    }
    if(e.itemIndex == 1){
      loadRanking();
    }
    console.log('Selected item #' + e.itemIndex + ' of section #' + e.sectionIndex);
    console.log('The item is titled "' + e.item.title + '"');
  });
}

function is_png(image_url){
  console.log(image_url)
  console.log(image_url.indexOf('.png'))
  return image_url.indexOf('.png') > 0
}

function renderMatch(matchObj){
  console.log(matchObj);

  _.each(
    matchWindow.ui_elements.player_images,
    function(element, index, list){
      matchWindow.remove(element);
    }
  );

  if(is_png(matchObj.winner_team[0].image)){
    matchWindow.ui_elements.player_images[0] = new UI.Image({ position: new Vector2( 0  , 5   ), size: new Vector2(60, 60), image: matchObj.winner_team[0].image });
    matchWindow.add(matchWindow.ui_elements.player_images[0]);
  }
  if(is_png(matchObj.winner_team[1].image)){
    matchWindow.ui_elements.player_images[1] = new UI.Image({ position: new Vector2( 64 , 5   ), size: new Vector2(60, 60), image: matchObj.winner_team[1].image });
    matchWindow.add(matchWindow.ui_elements.player_images[1]);
  }
  if(is_png(matchObj.looser_team[0].image)){
    matchWindow.ui_elements.player_images[2] = new UI.Image({ position: new Vector2( 0  , 100 ), size: new Vector2(60, 60), image: matchObj.looser_team[0].image });
    matchWindow.add(matchWindow.ui_elements.player_images[2]);
  }
  if(is_png(matchObj.looser_team[1].image)){
    matchWindow.ui_elements.player_images[3] = new UI.Image({ position: new Vector2( 64 , 100 ), size: new Vector2(60, 60), image: matchObj.looser_team[1].image });
    matchWindow.add(matchWindow.ui_elements.player_images[3]);
  }

  _.each(
    matchWindow.ui_elements.player_names,
    function(element, index, list){
      matchWindow.remove(element);
    }
  );

  matchWindow.remove(matchWindow.ui_elements.score_text);

  matchWindow.ui_elements.player_names[0] = new UI.Text({ position: new Vector2(  0 ,   15 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.winner_team[0].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[1] = new UI.Text({ position: new Vector2( 64 ,   15 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.winner_team[1].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[2] = new UI.Text({ position: new Vector2(  0 , 110 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.looser_team[0].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[3] = new UI.Text({ position: new Vector2( 64 , 110 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.looser_team[1].short_name, textAlign: 'center' });

  matchWindow.ui_elements.score_text = new UI.Text({ position: new Vector2(  0 ,  66 ), size: new Vector2(144, 32), font: 'gothic-24-bold', text: matchObj.score, textAlign: 'center' });
  matchWindow.add(matchWindow.ui_elements.score_text);

  _.each(
    matchWindow.ui_elements.player_names,
    function(element, index, list){
      matchWindow.add(element);
    }
  );
}

renderMenu();
<commit_msg>add user details<commit_after>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');
var Vector2 = require('vector2');
var ajax = require('ajax');
var KickerAPI = require('kickerapi');

function setupMatchWindow(){
  var matchWindow = new UI.Window({
    fullscreen: true,
    action: {
      up: 'images/action_icon_up.png',
      down: 'images/action_icon_down.png',
      select: 'images/action_icon_reload.png'
    }
  });
  //144 x 168

  matchWindow.ui_elements = {};

  matchWindow.ui_elements.loadingText = new UI.Text({ position: new Vector2(  0 ,  66 ), size: new Vector2(144, 32), font: 'gothic-24-bold', text: 'Loading...', textAlign: 'center' });

  matchWindow.ui_elements.placeholder_images = [];
  matchWindow.ui_elements.placeholder_images[0] = new UI.Image({ position: new Vector2( 0  , 5   ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[1] = new UI.Image({ position: new Vector2( 64 , 5   ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[2] = new UI.Image({ position: new Vector2( 0  , 100 ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  matchWindow.ui_elements.placeholder_images[3] = new UI.Image({ position: new Vector2( 64 , 100 ), size: new Vector2(60, 60), image: 'images/default_user.png' });
  _.each(
    matchWindow.ui_elements.placeholder_images,
    function(element, index, list){
      matchWindow.add(element);
    }
  );

  matchWindow.ui_elements.score_rect = new UI.Rect({ position: new Vector2(  37 ,  72 ), size: new Vector2(70, 22), backgroundColor: 'clear', borderColor: 'white' });
  matchWindow.add(matchWindow.ui_elements.score_rect);

  matchWindow.ui_elements.player_names = [];
  matchWindow.ui_elements.player_images = [];

  matchWindow.currentMatchIndex = 0; //start with latest match
  matchWindow.on('click', 'up', function() {
    if(league.matches()) {
      matchWindow.currentMatchIndex--;
      if(matchWindow.currentMatchIndex < 0) { matchWindow.currentMatchIndex = 0 }
      renderMatch(league.matches()[matchWindow.currentMatchIndex]);
    }
  });

  matchWindow.on('click', 'down', function() {
    if(league.matches()) {
      matchWindow.currentMatchIndex++;
      if(matchWindow.currentMatchIndex > league.matches().length) { matchWindow.currentMatchIndex = league.matches().length-1 }
      renderMatch(league.matches()[matchWindow.currentMatchIndex]);
    }
  });

  matchWindow.on('click', 'select', function() {
    loadMatches();
  });

  return matchWindow;
}

function setupRankingWindow(){
  var menu = new UI.Menu({
    sections: [{
      title: 'Ranking',
      items: [{
        title: 'Loading...'
      }]
    }]
  });
  menu.on('select', function(e) {
    console.log('Selected' + e.itemIndex);
    console.log(rankingWindow.active_users[e.itemIndex].id)
    loadUserDetails(rankingWindow.active_users[e.itemIndex].id);
  });
  return menu;
}

function setupUserDetailWindow(){
  var card = new UI.Card({});
  return card;
}

var league = new KickerAPI.League('railslove');
var matchWindow = setupMatchWindow();
var rankingWindow = setupRankingWindow();
var userDetailWindow = setupUserDetailWindow();

function loadMatches(){
  matchWindow.add(matchWindow.ui_elements.loadingText);
  matchWindow.currentMatchIndex = 0;
  matchWindow.show();
  league.loadMatches(function(){
    matchWindow.remove(matchWindow.ui_elements.loadingText);
    renderMatch(league.matches()[0]);
  },
  function(data, status){
    console.log('error loading matches', data, status);
  });
}

function loadRanking(){
  rankingWindow.show();
  league.loadUsers(function(){
    console.log(league.users());
    rankingWindow.active_users = _.filter( league.users(), function(element){ return element.active; } );
    rankingWindow.items(0, _.map( rankingWindow.active_users, function(user) { return { title: user.name, subtitle: user.quote }; }));
  },
  function(data, status){
    console.log('error loading users', data, status);
  });
}

function loadUserDetails(id){
  userDetailWindow.show();
  league.loadUserDetails(id, function(user_details){
    console.log(user_details.name);
    userDetailWindow.prop('subtitle', user_details.quote + '');
    userDetailWindow.prop('title', user_details.name);
    var body_string = user_details.number_of_wins + ' - ' user_details.number_of_looses + '(' + user_details.percentage + ')';
    console.log(body_string);
    userDetailWindow.prop('body', body_string);
    if(is_png(user_details.image)){
      userDetailWindow.prop('icon', user_details.image);
    }
    else{
      userDetailWindow.prop('icon', 'images/default_user.png')
    }
  },
  function(data, status){
    console.log('error loading user', data, status);
  });
}

function renderMenu(){
  var menu = new UI.Menu({
    sections: [{
      title: 'Railslove Kickerapp',
      items: [{
        title: 'Matches',
        subtitle: 'All games'
      }, {
        title: 'Ranking',
        subtitle: 'How do the users rank'
      }]
    }]
  });
  menu.show()
  menu.on('select', function(e) {
    if(e.itemIndex == 0){
      loadMatches();
    }
    if(e.itemIndex == 1){
      loadRanking();
    }
  });
}

function is_png(image_url){
  return image_url.indexOf('.png') > 0
}

function renderMatch(matchObj){
  _.each(
    matchWindow.ui_elements.player_images,
    function(element, index, list){
      matchWindow.remove(element);
    }
  );

  if(is_png(matchObj.winner_team[0].image)){
    matchWindow.ui_elements.player_images[0] = new UI.Image({ position: new Vector2( 0  , 5   ), size: new Vector2(60, 60), image: matchObj.winner_team[0].image });
    matchWindow.add(matchWindow.ui_elements.player_images[0]);
  }
  if(is_png(matchObj.winner_team[1].image)){
    matchWindow.ui_elements.player_images[1] = new UI.Image({ position: new Vector2( 64 , 5   ), size: new Vector2(60, 60), image: matchObj.winner_team[1].image });
    matchWindow.add(matchWindow.ui_elements.player_images[1]);
  }
  if(is_png(matchObj.looser_team[0].image)){
    matchWindow.ui_elements.player_images[2] = new UI.Image({ position: new Vector2( 0  , 100 ), size: new Vector2(60, 60), image: matchObj.looser_team[0].image });
    matchWindow.add(matchWindow.ui_elements.player_images[2]);
  }
  if(is_png(matchObj.looser_team[1].image)){
    matchWindow.ui_elements.player_images[3] = new UI.Image({ position: new Vector2( 64 , 100 ), size: new Vector2(60, 60), image: matchObj.looser_team[1].image });
    matchWindow.add(matchWindow.ui_elements.player_images[3]);
  }

  _.each(
    matchWindow.ui_elements.player_names,
    function(element, index, list){
      matchWindow.remove(element);
    }
  );

  matchWindow.remove(matchWindow.ui_elements.score_text);

  matchWindow.ui_elements.player_names[0] = new UI.Text({ position: new Vector2(  0 ,   15 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.winner_team[0].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[1] = new UI.Text({ position: new Vector2( 64 ,   15 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.winner_team[1].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[2] = new UI.Text({ position: new Vector2(  0 , 110 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.looser_team[0].short_name, textAlign: 'center' });
  matchWindow.ui_elements.player_names[3] = new UI.Text({ position: new Vector2( 64 , 110 ), size: new Vector2(60, 60), font: 'gothic-24-bold', text: matchObj.looser_team[1].short_name, textAlign: 'center' });

  matchWindow.ui_elements.score_text = new UI.Text({ position: new Vector2(  0 ,  66 ), size: new Vector2(144, 32), font: 'gothic-24-bold', text: matchObj.score, textAlign: 'center' });
  matchWindow.add(matchWindow.ui_elements.score_text);

  _.each(
    matchWindow.ui_elements.player_names,
    function(element, index, list){
      matchWindow.add(element);
    }
  );
}

renderMenu();
<|endoftext|>


<commit_before>angular.module('bitcoincalc', ['calc', 'app']);

angular.module('calc', []).factory('apiService', function($http) {
	var api = {};
	//api.url = "http://blockchain.info/ticker?format=json&callback=JSON_CALLBACK";
	//api.url = "http://bitcoincharts.com/t/markets.json";
	api.url = "ticker.json";
	api.getRates = function(callback, error) {
		console.log('get rates');
		$http.get(api.url).success(callback).error(error);
	};

	return api;
});

angular.module('app', []).controller('uiController', function($scope, apiService) {
	$scope.rates = [];
	$scope.bitcoinAmount = 1;
	$scope.cur = null;
	$scope.curAmount = 0;
	$scope.init = function(param) {
		console.log('app init');
		$scope.refreshRates();
	};

	$scope.refreshRates = function() {
		console.log('refresh rates');
		apiService.getRates(function(rates) {
			for(var i=0;i<Object.keys(rates).length;i++) {
				var rate = {};
				rate.name = Object.keys(rates)[i];
				rate.last = rates[Object.keys(rates)[i]].last;
				rate.symbol = rates[Object.keys(rates)[i]].symbol;
				$scope.rates.push(rate);
			}
			if($scope.cur == null)
				$scope.cur = $scope.rates[0];
			$scope.btcAmountChanged();
		},
		function(data){
			console.log("error");
			console.log(data);
		});
	};

	$scope.convertToCurrency = function(amount) {
		$scope.bitcoinAmount = parseFloat($scope.bitcoinAmount);
		if($scope.bitcoinAmount >= 0 && typeof($scope.bitcoinAmount) == "number" && !isNaN($scope.bitcoinAmount) && $scope.bitcoinAmount != "")
			return amount * $scope.bitcoinAmount;
		return 0;
	};

	$scope.convertToBitcoin = function(amount) {
		$scope.curAmount = parseFloat($scope.curAmount);
		if($scope.curAmount >= 0 && typeof($scope.curAmount) == "number" && !isNaN($scope.curAmount) && $scope.bitcoinAmount != "")
			return amount / $scope.curAmount;
		return 0;
	};

	$scope.setCur = function(cur) {
		$scope.cur = cur.rate;
		$scope.curAmountChanged();
	};

	$scope.btcAmountChanged = function() {
		$scope.curAmount = $scope.convertToCurrency($scope.cur.last);
	};

	$scope.curAmountChanged = function() {
		$scope.bitcoinAmount = $scope.convertToBitcoin($scope.cur.last);
	};

});<commit_msg>Api module now broadcasts new currency rates to controller in every 15 mins, instead of using callbacks.<commit_after>angular.module('bitcoincalc', ['calc', 'app']);

angular.module('calc', []).factory('apiService', function($rootScope, $http) {
	var api = {};
	api.url = "ticker.json";
	api.refresh = 900000; // 15mins

	api.refreshRates = function() {
		$http.get(api.url).success(function(rates) {
			$rootScope.$broadcast('api.rates', rates);
		});
	};

	setInterval(function() {
		api.refreshRates();
	}, api.refresh);

	api.refreshRates();

	return api;
});

angular.module('app', []).controller('uiController', function($scope, apiService) {
	$scope.rates = [];
	$scope.bitcoinAmount = 1;
	$scope.cur = null;
	$scope.curAmount = 0;

	$scope.$on('api.rates', function(e, rates) {
		for(var i=0;i<Object.keys(rates).length;i++) {
			var rate = {};
			rate.name = Object.keys(rates)[i];
			rate.last = rates[Object.keys(rates)[i]].last;
			rate.symbol = rates[Object.keys(rates)[i]].symbol;
			$scope.rates.push(rate);
		}
		if($scope.cur == null)
			$scope.cur = $scope.rates[0];
		$scope.btcAmountChanged();
	});

	$scope.convertToCurrency = function(amount) {
		$scope.bitcoinAmount = parseFloat($scope.bitcoinAmount);
		if($scope.bitcoinAmount >= 0 && typeof($scope.bitcoinAmount) == "number" && !isNaN($scope.bitcoinAmount) && $scope.bitcoinAmount != "")
			return amount * $scope.bitcoinAmount;
		return 0;
	};

	$scope.convertToBitcoin = function(amount) {
		$scope.curAmount = parseFloat($scope.curAmount);
		if($scope.curAmount >= 0 && typeof($scope.curAmount) == "number" && !isNaN($scope.curAmount) && $scope.bitcoinAmount != "")
			return amount / $scope.curAmount;
		return 0;
	};

	$scope.setCur = function(cur) {
		$scope.cur = cur.rate;
		$scope.curAmountChanged();
	};

	$scope.btcAmountChanged = function() {
		$scope.curAmount = $scope.convertToCurrency($scope.cur.last);
	};

	$scope.curAmountChanged = function() {
		$scope.bitcoinAmount = $scope.convertToBitcoin($scope.cur.last);
	};

});<|endoftext|>


<commit_before>'use strict';
/* global d3: false, check: false, ChartBase, scrollPosition: false, tooltip */
/* exported bar */
var BarBase = function (selection, data, orientation) {
    this.selection = check.string(selection) ? d3.select(selection) : selection;
    this.data = data;
    var chart = this.chart = new ChartBase(this.selection, 'bar');
    var config = this.config = chart.config;
    orientation = this.orientation = orientation || 'horizontal';
    chart.xScale = d3.scale.ordinal();
    chart.yScale = d3.scale.linear();
    this.updateX = function (newData) {
        data = check.defined(newData) ? newData : data;
        var xScaleRange = orientation === 'horizontal' ? [0, config.paddedHeight()] : [0, config.paddedWidth()];
        chart.xScale
            .domain(data.map(function (d) {
                return d.name;
            }))
            .rangeRoundBands(xScaleRange, 0.1);
        var xAxisOrient = orientation === 'horizontal' ? 'left' : 'bottom';
        chart.xAxis = d3.svg.axis()
            .scale(chart.xScale)
            .orient(xAxisOrient);
    };
    this.updateY = function (newData) {
        data = check.defined(newData) ? newData : data;
        chart.yScale
            .domain([0, d3.max(data, function (d) {
                return d.value;
            })]);
        var yScaleRange = orientation === 'horizontal' ? [0, config.paddedWidth()] : [config.paddedHeight(), 0];
        chart.yScale.range(yScaleRange);
        var yAxisOrient = orientation === 'horizontal' ? 'bottom' : 'left';
        chart.yAxis = d3.svg.axis()
            .scale(chart.yScale)
            .orient(yAxisOrient);
    };
    this.updateX();
    this.updateY();

    config.tooltipHtml = function (d) {
        var html = '

';
        html += '
' + d.value + '
';
        return html;
    };
};

BarBase.prototype.renderXAxis = function () {
    var chart = this.chart;
    var config = this.config;
    var selection = chart.renderArea.append('g')
        .attr('class', 'x axis')
        .call(chart.xAxis);
    var text = selection.append('text')
        .attr('class', 'x label')
        .attr('text-anchor', 'middle');
    if (this.orientation === 'horizontal') {
        text.attr('transform', 'rotate(-90)')
            .attr('y', config.margin.left * -1)
            .attr('x', (config.paddedHeight() / 2) * -1)
            .attr('dy', '1em');
    } else {
        selection.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        text.attr('x', config.paddedWidth() / 2)
            .attr('y', 28);
    }
    return this;
};

BarBase.prototype.renderYAxis = function () {
    var chart = this.chart;
    var config = this.config;
    var selection = chart.renderArea.append('g')
        .attr('class', 'y axis')
        .call(chart.yAxis);
    if (this.orientation === 'horizontal') {
        selection.attr('transform', 'translate(0,' + config.paddedHeight() + ')')
            .append('text')
            .attr('class', 'label')
            .attr('text-anchor', 'middle')
            .attr('x', config.paddedWidth() / 2)
            .attr('y', 28);
    }
    else {
        selection.append('text')
            .attr('class', 'y label')
            .attr('transform', 'rotate(-90)')
            .attr('y', config.margin.left * -1)
            .attr('x', (config.paddedHeight() / 2) * -1)
            .attr('dy', '1em')
            .style('text-anchor', 'middle');
    }
    return this;
};

BarBase.prototype.renderBars = function () {
    var chart = this.chart;
    var data = this.data;
    var config = this.config;
    this.bars = chart.renderArea.selectAll('.bar')
        .data(data)
        .enter().append('rect')
        .attr('class', 'bar diagrammatica-tooltip-target')
        .attr('fill', function (d) {
            return chart.colors(d.value);
        })
        .on('mouseover', function (d) {
            tooltip.transition().style('opacity', 1);
            var parentBox = this.getBoundingClientRect();
            var tooltipBox = tooltip.node().getBoundingClientRect();
            var boxHeightOffset = (parentBox.height - tooltipBox.height) / 2;
            tooltip.html(config.tooltipHtml(d))
                .style('left', parentBox.right + 'px')
                .style('top', parentBox.top + scrollPosition().y + boxHeightOffset + 'px');
        })
        .on('mouseout', function () {
            tooltip.style('opacity', 0);
        });

    if (this.orientation === 'horizontal') {
        this.bars
            .attr('x', 0)
            .attr('y', function (d) {
                return chart.xScale(d.name);
            })
            .attr('width', function (d) {
                return chart.yScale(d.value);
            })
            .attr('height', chart.xScale.rangeBand());
    } else {
        this.bars
            .attr('x', function (d) {
                return chart.xScale(d.name);
            })
            .attr('y', function (d) {
                return chart.yScale(d.value);
            })
            .attr('width', chart.xScale.rangeBand())
            .attr('height', function (d) {
                return config.paddedHeight() - chart.yScale(d.value);
            });
    }

    return this;
};

BarBase.prototype.render = function () {
    this.renderXAxis();
    this.renderYAxis();
    this.renderBars();
    return this;
};

var bar = function (selection, data, orientation) {
    var barBase = new BarBase(selection, data, orientation).render();
    var chart = barBase.chart;
    var config = barBase.config;
    var updateX = barBase.updateX;
    var updateY = barBase.updateY;
    var bars = barBase.bars;
    var update = chart.update = function (newData) {
        data = check.defined(newData) ? newData : data;
        updateY(data);
        var yAxisSelection = chart.renderArea.select('.y.axis')
            .transition()
            .call(chart.yAxis);
        updateX(data);
        var xAxisSelection = chart.renderArea.select('.x.axis')
            .transition()
            .call(chart.xAxis);
        if (barBase.orientation === 'horizontal') {
            yAxisSelection.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        } else {
            xAxisSelection.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        }

        if (barBase.orientation === 'horizontal') {
            bars.data(data)
                .transition()
                .attr('y', function (d) {
                    return chart.xScale(d.name);
                })
                .attr('width', function (d) {
                    return chart.yScale(d.value);
                })
                .attr('height', chart.xScale.rangeBand());
        } else {
            bars.data(data)
                .transition()
                .attr('x', function (d) {
                    return chart.xScale(d.name);
                })
                .attr('y', function (d) {
                    return chart.yScale(d.value);
                })
                .attr('width', chart.xScale.rangeBand())
                .attr('height', function (d) {
                    return config.paddedHeight() - chart.yScale(d.value);
                });
        }
    };

    update.height = function (value) {
        var axis = barBase.orientation === 'horizontal' ? 'x' : 'y';
        return chart.height(value, function () {
            updateX();
            barBase.selection.select('.' + axis + '.axis .label')
                .transition()
                .attr('y', config.margin.left * -1)
                .attr('x', (config.paddedHeight() / 2) * -1);
        });
    };

    update.width = function (value) {
        var axis = barBase.orientation === 'horizontal' ? 'y' : 'x';
        return chart.width(value, function () {
            updateY();
            barBase.selection.select('.' + axis + '.axis .label')
                .transition()
                .attr('x', config.paddedWidth() / 2)
                .attr('y', 28);
        });
    };

    update.yAxisLabelText = function (value) {
        return chart.yAxisLabelText(value);
    };

    update.xAxisLabelText = function (value) {
        return chart.xAxisLabelText(value);
    };

    update.chartBase = function () {
        return chart;
    };

    update.updateY = function () {
        return updateY;
    };

    update.updateX = function () {
        return updateX;
    };

    update.bars = function () {
        return bars;
    };

    return update;
};
<commit_msg>Refactor bar<commit_after>'use strict';
/* global d3: false, check: false, ChartBase, scrollPosition: false, tooltip */
/* exported bar */
var BarBase = function (selection, data, orientation) {
    this.selection = check.string(selection) ? d3.select(selection) : selection;
    this.data = data;
    var chart = this.chart = new ChartBase(this.selection, 'bar');
    var config = this.config = chart.config;
    orientation = this.orientation = orientation || 'horizontal';
    var isHorizontal = this.isHorizontal = function () {
        return orientation === 'horizontal';
    };
    chart.xScale = d3.scale.ordinal();
    chart.yScale = d3.scale.linear();
    this.updateX = function (newData) {
        data = check.defined(newData) ? newData : data;
        var xScaleRange = isHorizontal() ? [0, config.paddedHeight()] : [0, config.paddedWidth()];
        chart.xScale
            .domain(data.map(function (d) {
                return d.name;
            }))
            .rangeRoundBands(xScaleRange, 0.1);
        var xAxisOrient = isHorizontal() ? 'left' : 'bottom';
        chart.xAxis = d3.svg.axis()
            .scale(chart.xScale)
            .orient(xAxisOrient);
    };
    this.updateY = function (newData) {
        data = check.defined(newData) ? newData : data;
        chart.yScale
            .domain([0, d3.max(data, function (d) {
                return d.value;
            })]);
        var yScaleRange = isHorizontal() ? [0, config.paddedWidth()] : [config.paddedHeight(), 0];
        chart.yScale.range(yScaleRange);
        var yAxisOrient = isHorizontal() ? 'bottom' : 'left';
        chart.yAxis = d3.svg.axis()
            .scale(chart.yScale)
            .orient(yAxisOrient);
    };
    this.updateX();
    this.updateY();

    config.tooltipHtml = function (d) {
        var html = '

';
        html += '
' + d.value + '
';
        return html;
    };
};

BarBase.prototype.renderXAxis = function () {
    var chart = this.chart;
    var config = this.config;
    var selection = chart.renderArea.append('g')
        .attr('class', 'x axis')
        .call(chart.xAxis);
    var text = selection.append('text')
        .attr('class', 'x label')
        .attr('text-anchor', 'middle');
    if (this.isHorizontal()) {
        text.attr('transform', 'rotate(-90)')
            .attr('y', config.margin.left * -1)
            .attr('x', (config.paddedHeight() / 2) * -1)
            .attr('dy', '1em');
    } else {
        selection.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        text.attr('x', config.paddedWidth() / 2)
            .attr('y', 28);
    }
    return this;
};

BarBase.prototype.renderYAxis = function () {
    var chart = this.chart;
    var config = this.config;
    var selection = chart.renderArea.append('g')
        .attr('class', 'y axis')
        .call(chart.yAxis);
    var text = selection.append('text')
        .attr('class', 'label')
        .attr('text-anchor', 'middle');
    if (this.isHorizontal()) {
        selection.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        text.attr('x', config.paddedWidth() / 2)
            .attr('y', 28);
    }
    else {
        text.attr('transform', 'rotate(-90)')
            .attr('x', (config.paddedHeight() / 2) * -1)
            .attr('y', config.margin.left * -1)
            .attr('dy', '1em');
    }
    return this;
};

BarBase.prototype.renderBars = function () {
    var chart = this.chart;
    var data = this.data;
    var config = this.config;
    this.bars = chart.renderArea.selectAll('.bar')
        .data(data)
        .enter().append('rect')
        .attr('class', 'bar diagrammatica-tooltip-target')
        .attr('fill', function (d) {
            return chart.colors(d.value);
        })
        .on('mouseover', function (d) {
            tooltip.transition().style('opacity', 1);
            var parentBox = this.getBoundingClientRect();
            var tooltipBox = tooltip.node().getBoundingClientRect();
            var boxHeightOffset = (parentBox.height - tooltipBox.height) / 2;
            tooltip.html(config.tooltipHtml(d))
                .style('left', parentBox.right + 'px')
                .style('top', parentBox.top + scrollPosition().y + boxHeightOffset + 'px');
        })
        .on('mouseout', function () {
            tooltip.style('opacity', 0);
        });
    var x = 0;
    var y = function (d) {
        return chart.xScale(d.name);
    };
    var width = function (d) {
        return chart.yScale(d.value);
    };
    var height = chart.xScale.rangeBand();
    if (!this.isHorizontal()) {
        x = function (d) {
            return chart.xScale(d.name);
        };
        y = function (d) {
            return chart.yScale(d.value);
        };
        width = chart.xScale.rangeBand();
        height = function (d) {
            return config.paddedHeight() - chart.yScale(d.value);
        };
    }
    this.bars
        .attr('x', x)
        .attr('y', y)
        .attr('width', width)
        .attr('height', height);
    return this;
};

BarBase.prototype.render = function () {
    this.renderXAxis();
    this.renderYAxis();
    this.renderBars();
    return this;
};

var bar = function (selection, data, orientation) {
    var barBase = new BarBase(selection, data, orientation).render();
    var chart = barBase.chart;
    var config = barBase.config;
    var updateX = barBase.updateX;
    var updateY = barBase.updateY;
    var bars = barBase.bars;
    var update = chart.update = function (newData) {
        data = check.defined(newData) ? newData : data;
        updateY(data);
        var yAxisSelection = chart.renderArea.select('.y.axis')
            .transition()
            .call(chart.yAxis);
        updateX(data);
        var xAxisSelection = chart.renderArea.select('.x.axis')
            .transition()
            .call(chart.xAxis);
        var axisToTranslate = barBase.isHorizontal() ? yAxisSelection : xAxisSelection;
        axisToTranslate.attr('transform', 'translate(0,' + config.paddedHeight() + ')');
        var barTransition = bars.data(data)
            .transition();
        if (barBase.isHorizontal()) {
            barTransition
                .attr('y', function (d) {
                    return chart.xScale(d.name);
                })
                .attr('width', function (d) {
                    return chart.yScale(d.value);
                })
                .attr('height', chart.xScale.rangeBand());
        } else {
            barTransition
                .attr('x', function (d) {
                    return chart.xScale(d.name);
                })
                .attr('y', function (d) {
                    return chart.yScale(d.value);
                })
                .attr('width', chart.xScale.rangeBand())
                .attr('height', function (d) {
                    return config.paddedHeight() - chart.yScale(d.value);
                });
        }
    };

    update.height = function (value) {
        var axis = barBase.isHorizontal() ? 'x' : 'y';
        return chart.height(value, function () {
            updateX();
            barBase.selection.select('.' + axis + '.axis .label')
                .transition()
                .attr('y', config.margin.left * -1)
                .attr('x', (config.paddedHeight() / 2) * -1);
        });
    };

    update.width = function (value) {
        var axis = barBase.isHorizontal() ? 'y' : 'x';
        return chart.width(value, function () {
            updateY();
            barBase.selection.select('.' + axis + '.axis .label')
                .transition()
                .attr('x', config.paddedWidth() / 2)
                .attr('y', 28);
        });
    };

    update.yAxisLabelText = function (value) {
        return chart.yAxisLabelText(value);
    };

    update.xAxisLabelText = function (value) {
        return chart.xAxisLabelText(value);
    };

    update.chartBase = function () {
        return chart;
    };

    update.updateY = function () {
        return updateY;
    };

    update.updateX = function () {
        return updateX;
    };

    update.bars = function () {
        return bars;
    };

    return update;
};
<|endoftext|>


<commit_before>
	HTM = {};

	HTM.init = function()  {

		let container;
		const b = '
';

		container = document.body.appendChild( document.createElement( 'div' ) );
		container.id = 'container';
		container.innerHTML =

			'
' +

				'
' +
					'' + b +
					'' + 'eyeCue Replay R1' + '' +
					'  ⓘ ' +
				'
' +

				'

Hi there!
Click the i-in-circle, info icon for latest updates.
' +
				'
' + document.head.querySelector("[name=description]").content + '
' +

				'

' +

				'

' +

				'

' +

				'' +
					'
About
' +

					'
' +
						'• Rotate|Zoom|Pan => 1|2|3' + b +
						'  fingers/buttons' + b +
						'• Rotation => spacebar' + b +
						'• Slide menu => \'hamburger\' icon' +
					'
' +

					'
Click the \'i in a circle\' icon for more help.
' +

					'
' +
						'Keywords:' + b +
						document.head.querySelector("[name=keywords]").content.replace( /,/g, ', ' ) + b + b +
						'Revision Date:' + b +
						document.head.querySelector("[name=date]").content + b + b +
						'File name:' + b +
						location.pathname.split( '/' ).pop() + b +
					'
' +

					'
Copyright © ' + ( new Date() ).getFullYear() + ' predIQtiv authors. MIT license.
' +

				'' +

				'
' +

				'

' +
				'
predIQtiv - invest smarter.
Click here to return to the top of the page
' +

			'
' +

			'
' +
				'
 &#9776
' +
			'
' +

			'
 ⌂
' +

		'';

	}
<commit_msg>update release #1<commit_after>
	HTM = {};

	HTM.init = function()  {

		let container;
		const b = '
';

		container = document.body.appendChild( document.createElement( 'div' ) );
		container.id = 'container';
		container.innerHTML =

			'
' +

				'
' +
					'' + b +
					'' + 'eyeCue Replay R1.1' + '' +
					'  ⓘ ' +
				'
' +

				'

Hi there!
Click the i-in-circle, info icon for latest updates.
' +
				'
' + document.head.querySelector("[name=description]").content + '
' +

				'

' +

				'

' +

				'

' +

				'' +
					'
About
' +

					'
' +
						'• Rotate|Zoom|Pan => 1|2|3' + b +
						'  fingers/buttons' + b +
						'• Rotation => spacebar' + b +
						'• Slide menu => \'hamburger\' icon' +
					'
' +

					'
Click the \'i in a circle\' icon for more help.
' +

					'
' +
						'Keywords:' + b +
						document.head.querySelector("[name=keywords]").content.replace( /,/g, ', ' ) + b + b +
						'Revision Date:' + b +
						document.head.querySelector("[name=date]").content + b + b +
						'File name:' + b +
						location.pathname.split( '/' ).pop() + b +
					'
' +

					'
Copyright © ' + ( new Date() ).getFullYear() + ' predIQtiv authors. MIT license.
' +

				'' +

				'
' +

				'

' +
				'
predIQtiv - invest smarter.
Click here to return to the top of the page
' +

			'
' +

			'
' +
				'
 &#9776
' +
			'
' +

			'
 ⌂
' +

		'';

	}
<|endoftext|>


<commit_before>/* ==========================================================
 * DOM sugar (VK Offline Chrome app)
 * https://github.com/1999/vkoffline
 * ==========================================================
 * Copyright 2013 Dmitry Sorin <info@staypositive.ru>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

(function (w) {
	window.$ = function () {
		switch (arguments.length) {
			case 1:
				if (arguments[0] instanceof HTMLElement)
					return arguments[0];

				if (typeof arguments[0] === "string") {
					if (!/^<(.|[\r\n\t])+>$/.test(arguments[0]))
						return document.querySelector(arguments[0]);

					// $("
text
")
					var tmpElem = document.createElement("div");
					tmpElem.innerHTML = arguments[0];

					return (tmpElem.childNodes.length > 1) ? tmpElem.childNodes : tmpElem.firstChild;
				}

				break;

			case 2:
				if (arguments[0] instanceof HTMLElement && typeof arguments[1] === "string")
					return arguments[0].querySelector(arguments[1]);

				break;
		}

		throw new Error("Can't use these arguments");
	};

	window.$$ = function () {
		switch (arguments.length) {
			case 1:
				if (typeof arguments[0] === "string")
					return document.querySelectorAll(arguments[0]);

				break;

			case 2:
				if (arguments[0] instanceof HTMLElement && typeof arguments[1] === "string")
					return arguments[0].querySelectorAll(arguments[1]);

				break;
		}

		throw new Error("Can't use these arguments");
	};

	HTMLElement.prototype.__proto__ = Object.create(Object.getPrototypeOf(HTMLElement.prototype), {
		closestParent: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (selector) {
				var matchesSelectorFn = (Element.prototype.webkitMatchesSelector || Element.prototype.matchesSelector);
				var elem = this;

				while (elem.parentNode) {
					if (matchesSelectorFn.call(elem, selector))
						return elem;

					elem = elem.parentNode;
				}

				return null;
			}
		},
		bind: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (evtType, callback, singleton) {
				if (singleton) {
					this["on" + evtType] = callback;
				} else {
					this.addEventListener(evtType, callback, false);
				}

				return this;
			}
		},
		remove: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				return this.parentNode.removeChild(this);
			}
		},
		html: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (newHTML) {
				if (newHTML !== undefined) {
					this.innerHTML = newHTML;
					return this;
				}

				return this.innerHTML;
			}
		},
		text: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (newContent) {
				if (newContent !== undefined) {
					this.textContent = newContent;
					return this;
				}

				return this.textContent;
			}
		},
		empty: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				return this.html("");
			}
		},

		/**
		 * @param {String|Array|HTMLElement} contents
		 */
		append: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (contents) {
				if (typeof contents === "string") {
					this.insertAdjacentHTML("beforeEnd", contents);
				} else {
					if (contents instanceof HTMLElement)
						contents = [contents];

					for (var i = 0; i < contents.length; i++) {
						this.insertAdjacentElement("beforeEnd", contents[i]);
					}
				}

				return this;
			}
		},

		/**
		 * @param {String|Array|HTMLElement} contents
		 */
		prepend: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (contents) {
				if (typeof contents === "string") {
					this.insertAdjacentHTML("afterBegin", contents);
				} else {
					if (contents instanceof HTMLElement)
						contents = [contents];

					for (var i = contents.length - 1; i >= 0; i--) {
						this.insertAdjacentElement("afterBegin", contents[i]);
					}
				}

				return this;
			}
		},

		/**
		 * @param {String|Array|HTMLElement} contents
		 */
		before: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (contents) {
				if (typeof contents === "string") {
					this.insertAdjacentHTML("beforeBegin", contents);
				} else {
					if (contents instanceof HTMLElement)
						contents = [contents];

					for (var i = 0; i < contents.length; i++) {
						this.insertAdjacentElement("beforeBegin", contents[i]);
					}
				}

				return this;
			}
		},

		/**
		 * @param {String|Array|HTMLElement} contents
		 */
		after: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (contents) {
				if (typeof contents === "string") {
					this.insertAdjacentHTML("afterEnd", contents);
				} else {
					if (contents instanceof HTMLElement)
						contents = [contents];

					for (var i = 0; i < contents.length; i++) {
						this.insertAdjacentElement("afterEnd", contents[i]);
					}
				}

				return this;
			}
		},
		val: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (newValue) {
				if (newValue === undefined)
					return this.value;

				this.value = newValue;
				return this;
			}
		},
		addClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var classNames = Array.prototype.slice.call(arguments, 0);
				for (var i = 0; i < classNames.length; i++)
					this.classList.add(classNames[i]);

				return this;
			}
		},

		/**
		 * if multiple aguments are supplied, checks whether all of them are in the classList
		 */
		hasClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var classNames = Array.prototype.slice.call(arguments, 0);
				var contains = true;

				for (var i = 0; i < classNames.length; i++) {
					if (!this.classList.contains(classNames[i])) {
						contains = false;
						break;
					}
				}

				return contains;
			}
		},
		toggleClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (className, force) {
				return this.classList.toggle(className, force);
			}
		},

		/**
		 * if no aguments are supplied, clears all classes from the DOM element(s)
		 */
		removeClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var classNames = Array.prototype.slice.call(arguments, 0);
				if (classNames.length) {
					for (var i = 0; i < classNames.length; i++) {
						this.classList.remove(classNames[i]);
					}
				} else {
					this.className = "";
				}

				return this;
			}
		},
		attr: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (key, value) {
				if (value === undefined && typeof key === "string")
					return this.getAttribute(key);

				var attributes = {};
				if (arguments.length === 1) {
					attributes = key;
				} else {
					attributes[key] = value;
				}

				for (var key in attributes)
					this.setAttribute(key, attributes[key]);

				return this;
			}
		},
		removeAttr: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (key) {
				this.removeAttribute(key);
				return this;
			}
		},
		data: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (key, value) {
				if (value === undefined && typeof key === "string")
					return (this.dataset[key] || "");

				var data = {};
				if (arguments.length === 1) {
					data = key;
				} else {
					data[key] = value;
				}

				for (var key in data)
					this.dataset[key] = data[key];

				return this;
			}
		},

		/**
		 * if no aguments are supplied, clears all dataset from the DOM element(s)
		 */
		removeData: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var datasetKeys = Array.prototype.slice.call(arguments, 0);

				for (var key in this.dataset) {
					if (!datasetKeys.length || datasetKeys.indexOf(key) !== -1) {
						delete this.dataset[key];
					}
				}

				return this;
			}
		},
		css: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (key, value) {
				if (value === undefined && typeof key === "string")
					return this.style[key];

				var styles = {};
				if (arguments.length === 1) {
					styles = key;
				} else {
					styles[key] = value;
				}

				for (var key in styles)
					this.style[key] = styles[key];

				return this;
			}
		}
	});

	NodeList.prototype.__proto__ = Object.create(Object.getPrototypeOf(NodeList.prototype), {
		each: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (fn) {
				for (var i = 0; i < this.length; i++) {
					fn.call(this[i], i);
				}
			}
		},
		bind: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function (evtType, callback) {
				for (var i = 0; i < this.length; i++)
					this[i].addEventListener(evtType, callback, false);

				return this;
			}
		},
		empty: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				for (var i = 0; i < this.length; i++) {
					this[i].empty();
				}
			}
		},
		remove: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				for (var i = 0; i < this.length; i++) {
					this[i].parentNode.removeChild(this[i]);
				}
			}
		},
		addClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var classNames = Array.prototype.slice.call(arguments, 0);
				for (var i = 0; i < classNames.length; i++) {
					for (var j = 0; j < this.length; j++) {
						this[j].classList.add(classNames[i]);
					}
				}

				return this;
			}
		},

		/**
		 * if no aguments are supplied, clears all classes from the DOM element(s)
		 */
		removeClass: {
			writable: false,
			configurable: false,
			enumerable: false,
			value: function () {
				var classNames = Array.prototype.slice.call(arguments, 0);
				var i, j;

				if (classNames.length) {
					for (i = 0; i < classNames.length; i++) {
						for (j = 0; j < this.length; j++) {
							this[j].classList.remove(classNames[i]);
						}
					}
				} else {
					for (j = 0; j < this.length; j++) {
						this[j].className = "";
					}
				}

				return this;
			}
		}
	});
})();
<commit_msg>Add DOM latest version<commit_after>/* ==========================================================
 * DOM sugar for new browsers
 * https://github.com/1999/dom
 * ==========================================================
 * Copyright 2013 Dmitry Sorin <info@staypositive.ru>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

(function () {
    // shim for browsers with missing support for insertAdjacentElement
    if (!HTMLElement.prototype.insertAdjacentElement) {
        var adjacentElementDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "insertAdjacentHTML");
        adjacentElementDescriptor.value = function (where, parsedNode) {
            switch (where) {
                case "beforeBegin":
                    this.parentNode.insertBefore(parsedNode, this);
                    break;

                case "afterBegin":
                    this.insertBefore(parsedNode, this.firstChild);
                    break;

                case "beforeEnd":
                    this.appendChild(parsedNode);
                    break;

                case "afterEnd":
                    if (this.nextSibling)
                        this.parentNode.insertBefore(parsedNode, this.nextSibling);
                    else
                        this.parentNode.appendChild(parsedNode);

                    break;
            }
        }

        Object.defineProperty(HTMLElement.prototype, "insertAdjacentElement", adjacentElementDescriptor);
    }

    var HTMLExtendedElement = {
        /**
         * Find closest ancestor node
         * @param {String} selector
         * @return {HTMLElement|Null}
         */
        closestParent: function (selector) {
            var matchesSelectorFn = (Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector);
            var elem = this;

            while (elem.parentNode) {
                if (matchesSelectorFn.call(elem, selector))
                    return elem;

                elem = elem.parentNode;
            }

            return null;
        },
        /**
         * Bind event listener to node
         * @param {String} evtType
         * @param {Function} callback
         * @param {Boolean} singleton
         * @return {HTMLElement} refers to this
         */
        bind: function (evtType, callback, singleton) {
            if (singleton) {
                this["on" + evtType] = callback;
            } else {
                this.addEventListener(evtType, callback, false);
            }

            return this;
        },
        /**
         * Remove node
         * @return {HTMLElement} refers to this
         */
        remove: function () {
            return this.parentNode.removeChild(this);
        },
        /**
         * Get innerHTML property of a node or set it
         * @param {String|Undefined} newHTML
         * @return {HTMLElement|String} innerHTML or node which refers to this
         */
        html: function (newHTML) {
            if (newHTML !== undefined) {
                this.innerHTML = newHTML;
                return this;
            }

            return this.innerHTML;
        },
        /**
         * Get textContent property of a node or set it
         * @param {String|Undefined} newContent
         * @return {HTMLElement|String} textContent or node which refers to this
         */
        text: function (newContent) {
            if (newContent !== undefined) {
                this.textContent = newContent;
                return this;
            }

            return this.textContent;
        },
        /**
         * Empty innerHTML of a node
         * @type {HTMLElement} refers to this
         */
        empty: function () {
            return this.html("");
        },
        /**
         * Append HTML code, HTMLElement or NodeList to a node
         * @param {String|HTMLElement|NodeList} contents
         * @return {HTMLElement} refers to this
         */
        append: function (contents) {
            if (typeof contents === "string") {
                this.insertAdjacentHTML("beforeEnd", contents);
            } else if (contents instanceof HTMLElement) {
                this.insertAdjacentElement("beforeEnd", contents);
            } else if (contents instanceof NodeList) {
                for (var i = 0; i < contents.length; i++) {
                    this.insertAdjacentElement("beforeEnd", contents[i]);
                }
            }

            return this;
        },
        /**
         * Insert HTML code, HTMLElement or NodeList to the beginning of a node contents
         * @param {String|HTMLElement|NodeList} contents
         * @return {HTMLElement} refers to this
         */
        prepend: function (contents) {
            if (typeof contents === "string") {
                this.insertAdjacentHTML("afterBegin", contents);
            } else if (contents instanceof HTMLElement) {
                this.insertAdjacentElement("afterBegin", contents);
            } else if (contents instanceof NodeList) {
                for (var i = 0; i < contents.length; i++) {
                    this.insertAdjacentElement("afterBegin", contents[i]);
                }
            }

            return this;
        },
        /**
         * Insert HTML code, HTMLElement or NodeList before a node
         * @param {String|HTMLElement|NodeList} contents
         * @return {HTMLElement} refers to this
         */
        before: function (contents) {
            if (typeof contents === "string") {
                this.insertAdjacentHTML("beforeBegin", contents);
            } else if (contents instanceof HTMLElement) {
                this.insertAdjacentElement("beforeBegin", contents);
            } else if (contents instanceof NodeList) {
                for (var i = 0; i < contents.length; i++) {
                    this.insertAdjacentElement("beforeBegin", contents[i]);
                }
            }

            return this;
        },
        /**
         * Insert HTML code, HTMLElement or NodeList after a node
         * @param {String|HTMLElement|NodeList} contents
         * @return {HTMLElement} refers to this
         */
        after: function (contents) {
            if (typeof contents === "string") {
                this.insertAdjacentHTML("afterEnd", contents);
            } else if (contents instanceof HTMLElement) {
                this.insertAdjacentElement("afterEnd", contents);
            } else if (contents instanceof NodeList) {
                for (var i = 0; i < contents.length; i++) {
                    this.insertAdjacentElement("afterEnd", contents[i]);
                }
            }

            return this;
        },
        /**
         * Get value of a node or set it
         * @param {Mixed|Undefined} newValue
         * @return {HTMLElement|Mixed} node value or node which refers to this
         */
        val: function (newValue) {
            if (newValue === undefined)
                return this.value;

            this.value = newValue;
            return this;
        },
        /**
         * Add one or mutiple classes to a node classList
         * @param [arguments] classNames
         * @return {HTMLElement} refers to this
         */
        addClass: function () {
            var classNames = Array.prototype.slice.call(arguments, 0);
            for (var i = 0; i < classNames.length; i++)
                this.classList.add(classNames[i]);

            return this;
        },
        /**
         * Remove one or mutiple classes from a node classList. If arguments count is 0, than classList is cleared
         * @param [arguments] classNames
         * @return {HTMLElement} refers to this
         */
        removeClass: function () {
            var classNames = Array.prototype.slice.call(arguments, 0);
            if (classNames.length) {
                for (var i = 0; i < classNames.length; i++) {
                    this.classList.remove(classNames[i]);
                }
            } else {
                this.className = "";
            }

            return this;
        },
        /**
         * Check whether one or all of the classes are in the classList property of a node
         * @param [arguments] classNames
         * @return {Boolean}
         */
        hasClass: function () {
            var classNames = Array.prototype.slice.call(arguments, 0);
            var contains = true;

            for (var i = 0; i < classNames.length; i++) {
                if (!this.classList.contains(classNames[i])) {
                    contains = false;
                    break;
                }
            }

            return contains;
        },
        /**
         * Toggle the existence of a class in an element's list of classes
         * @type {Boolean}
         */
        toggleClass: function (className, force) {
            return this.classList.toggle(className, force);
        },
        /**
         * Get attribute(s) of a node or set it
         * @param {String} key
         * @param {Mixed} value
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {Object} key-value map of the attributes
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {String} key
         * @return {Mixed} attribute's value
         */
        attr: function (key, value) {
            if (value === undefined && typeof key === "string")
                return this.getAttribute(key);

            var attributes = {};
            if (arguments.length === 1) {
                attributes = key;
            } else {
                attributes[key] = value;
            }

            for (var attrKey in attributes)
                this.setAttribute(attrKey, attributes[key]);

            return this;
        },
        /**
         * Remove node's attribute
         * @return {HTMLElement} refers to this
         */
        removeAttr: function (key) {
            this.removeAttribute(key);
            return this;
        },
        /**
         * Get dataset value(s) or set it
         * @param {String} key
         * @param {Mixed} value
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {Object} key-value map of the dataset
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {String} key
         * @return {Mixed} attribute's value
         */
        data: function (key, value) {
            if (value === undefined && typeof key === "string")
                return (this.dataset[key] || "");

            var data = {};
            if (arguments.length === 1) {
                data = key;
            } else {
                data[key] = value;
            }

            for (var dataKey in data)
                this.dataset[dataKey] = data[key];

            return this;
        },
        /**
         * Delete dataset properties from a node. If arguments count is 0, than dataset of a node will be cleared
         * @param [arguments] dataset keys
         * @return {HTMLElement} refers to this
         */
        removeData: function () {
            var datasetKeys = Array.prototype.slice.call(arguments, 0);

            for (var key in this.dataset) {
                if (!datasetKeys.length || datasetKeys.indexOf(key) !== -1) {
                    delete this.dataset[key];
                }
            }

            return this;
        },
        /**
         * Get style property value(s) of a node or set it
         * @param {String} key
         * @param {Mixed} value
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {Object} key-value map of the dataset
         * @return {HTMLElement} refers to this
         *
         * or
         * @param {String} key
         * @return {Mixed} attribute's value
         */
        css: function (key, value) {
            if (value === undefined && typeof key === "string")
                return this.style[key];

            var styles = {};
            if (arguments.length === 1) {
                styles = key;
            } else {
                styles[key] = value;
            }

            for (var cssKey in styles)
                this.style[cssKey] = styles[key];

            return this;
        }
    };

    var NodeExtendedList = {
        /**
         * Apply callback to each element of the list
         * @param {Function} callback where this refers to parsed element of the list
         * @return {NodeList} refers to this
         */
        each: function (callback) {
            for (var i = 0; i < this.length; i++)
                callback.call(this[i], i);

            return this;
        },
        /**
         * Bind event listener to every element of the list
         * @param {String} evtType
         * @param {Function} callback
         * @param {Boolean} singleton
         * @return {NodeList} refers to this
         */
        bind: function (evtType, callback, singleton) {
            for (var i = 0; i < this.length; i++)
                this[i].bind(evtType, callback, singleton);

            return this;
        },
        /**
         * Empty innerHTML properties of every element in the list
         * @return {NodeList} refers to this
         */
        empty: function () {
            for (var i = 0; i < this.length; i++)
                this[i].empty();

            return this;
        },
        /**
         * Remove every element of the list from their parents
         * @return {NodeList} refers to this
         */
        remove: function () {
            for (var i = 0; i < this.length; i++)
                this[i].remove();

            return this;
        },
        /**
         * Add one or mutiple classes to every element's classList
         * @param [arguments] classNames
         * @return {NodeList} refers to this
         */
        addClass: function () {
            for (var i = 0; i < this.length; i++)
                this[i].addClass.apply(this[i], Array.prototype.slice.call(arguments, 0));

            return this;
        },
        /**
         * Remove one or mutiple classes from every element's classList. If arguments count is 0, than classList is cleared
         * @return {NodeList} refers to this
         */
        removeClass: function () {
            for (var i = 0; i < this.length; i++)
                this[i].removeClass.apply(this[i], Array.prototype.slice.call(arguments, 0));

            return this;
        }
    };

    var elementPropertiesObject = {};
    for (var methodName in HTMLExtendedElement) {
        elementPropertiesObject[methodName] = {
            value: HTMLExtendedElement[methodName]
        };
    }

    var listPropertiesObject = {};
    for (var methodName in NodeExtendedList) {
        listPropertiesObject[methodName] = {
            value: NodeExtendedList[methodName]
        };
    }

    /**
     * Shortened and more convenient "querySelector"
     * @return {HTMLElement|Null}
     * @throws {TypeError} if arguments are invalid
     *
     * @example
     * $(document.body) returns a document body itself
     * $("
smth
") returns a new div element with innerHTML property set to "smth"
     * $("div.wrapper p") returns the same as document.querySelector("div.wrapper p")
     * $(parentNode, "p") returns the same as parentNode.querySelector("p")
     */
    window.$ = function () {
        switch (arguments.length) {
            case 1:
                if (arguments[0] instanceof HTMLElement)
                    return arguments[0];

                if (typeof arguments[0] === "string") {
                    if (!/^<(.|[\r\n\t])+>$/.test(arguments[0]))
                        return document.querySelector(arguments[0]);

                    var tmpElem = document.createElement("div");
                    tmpElem.innerHTML = arguments[0];
                    return tmpElem.firstChild;
                }

                break;

            case 2:
                if (arguments[0] instanceof HTMLElement && typeof arguments[1] === "string")
                    return arguments[0].querySelector(arguments[1]);

                break;
        }

        throw new TypeError("Can't use these arguments");
    };

    /**
     * Shortened and more convenient "querySelectorAll"
     * @return {NodeList}
     * @throws {TypeError} if arguments are invalid
     *
     * @example
     * $$(nodeList) returns a nodeList itself
     * $$("div.wrapper p") returns the same as document.querySelectorAll("div.wrapper p")
     * $$(parentNode, "p") returns the same as parentNode.querySelectorAll("p")
     */
    window.$$ = function () {
        switch (arguments.length) {
            case 1:
                if (arguments[0] instanceof NodeList)
                    return arguments[0];

                if (typeof arguments[0] === "string")
                    return document.querySelectorAll(arguments[0]);

                break;

            case 2:
                if (arguments[0] instanceof HTMLElement && typeof arguments[1] === "string")
                    return arguments[0].querySelectorAll(arguments[1]);

                break;
        }

        throw new TypeError("Can't use these arguments");
    };

    HTMLElement.prototype.__proto__ = Object.create(Object.getPrototypeOf(HTMLElement.prototype), elementPropertiesObject);
    NodeList.prototype.__proto__ = Object.create(Object.getPrototypeOf(NodeList.prototype), listPropertiesObject);
})();<|endoftext|>