<commit_before>/**                        __                          __
  _____    ____    ____  _/  |_       _____    ____  _/  |_   ____    ____  _______
 /     \ _/ __ \ _/ __ \ \   __\     /     \ _/ __ \ \   __\_/ __ \  /  _ \ \_  __ \
|  Y Y  \\  ___/ \  ___/  |  |      |  Y Y  \\  ___/  |  |  \  ___/ (  <_> ) |  | \/
|__|_|  / \___  > \___  > |__|      |__|_|  / \___  > |__|   \___  > \____/  |__|
      \/      \/      \/                  \/      \/             \/

Reactivity! - How to template.
See README.md for walkthrough...
*/

var Mustaches = new Meteor.Collection('mustaches');

if (Meteor.isClient) {

  var straps = [
    "A hotchpotch of handlebars",
    "Curly braces for a lovely faces",
    "Markup grooming maketh man",
    "Temple of plate brushes",
  ]

  Template.header.strapline = function () {
    return straps[getRandomInt(0, straps.length - 1)]
  };

  Template.header.events({
    click: function (evt) {
      $('header span').html(Template.header.strapline());
    },
  });

  Template.mustaches.isEmpty = function () {
    return Mustaches.find().count() < 1;
  }

  Template.mustaches.allOfThem = function () {
    return Mustaches.find({}, {sort:[['createdDate','desc']]});
  };

  Template.search.events({
    submit: function (evt) {
      evt.preventDefault();

      var term = $('#searchInput').val()

      console.log($('#searchInput').val())

      var stachId = Mustaches.insert({createdDate: Date.now(), name: term});

      findGif(term, function(url){
        // Mustaches.update(stachId, {img: url});
        Mustaches.update(stachId, {$set: {img: url}});
      });

    },
  });

  function findGif(search, cb) {
    $.getJSON("http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q="+search+"+moustache+animated+filetype:gif&callback=?",
    function(data){
      $.each(data.responseData.results, function(i,item){
        cb(item.unescapedUrl);
        if ( i == 0 ) return false;
      });
    });
  }

  // TRY ME: Replace this with http://docs.meteor.com/#random
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }
}

<commit_msg>Simplify random strapline code for moustachery<commit_after>/**                        __                          __
  _____    ____    ____  _/  |_       _____    ____  _/  |_   ____    ____  _______
 /     \ _/ __ \ _/ __ \ \   __\     /     \ _/ __ \ \   __\_/ __ \  /  _ \ \_  __ \
|  Y Y  \\  ___/ \  ___/  |  |      |  Y Y  \\  ___/  |  |  \  ___/ (  <_> ) |  | \/
|__|_|  / \___  > \___  > |__|      |__|_|  / \___  > |__|   \___  > \____/  |__|
      \/      \/      \/                  \/      \/             \/

Reactivity! - How to template.
See ../README.md for walkthrough
*/

// Collection is shared between client and server
var Mustaches = new Meteor.Collection('mustaches');

if (Meteor.isClient) {

  // Non-reactive, plain old array.
  var straps = [
    "A hotchpotch of handlebars",
    "Curly braces for a lovely faces",
    "Markup grooming maketh man",
    "Temple of plate brushes"
  ]

  function randomStrapLine () {
    return straps[getRandomInt(0, straps.length - 1)]
  }

  // Store a random strapline in the reactive Session object on the client.
  Session.set('strapline', randomStrapLine());

  // Add a helper to retrieve a strapline
  Template.header.strapline = function () {
    // Meteor notices this templates is dependant on the Session's strapline value, and will re-render when it chages.
    return Session.get('strapline');
  };

  // on click: pick another random strapline and set it on the Session
  Template.header.events({
    click: function (evt) {
      Session.set('strapline', randomStrapLine());
    },
  });

  Template.mustaches.isEmpty = function () {
    return Mustaches.find().count() < 1;
  }

  Template.mustaches.allOfThem = function () {
    return Mustaches.find({}, {sort:[['createdDate','desc']]});
  };

  Template.search.events({
    submit: function (evt) {
      evt.preventDefault();

      var term = $('#searchInput').val()

      console.log($('#searchInput').val())

      var stachId = Mustaches.insert({createdDate: Date.now(), name: term});

      findImg(term, function(url){
        // Mustaches.update(stachId, {img: url});
        Mustaches.update(stachId, {$set: {img: url}});
      });

    },
  });

  function findImg(search, cb) {
    // add `+animated+filetype:gif` to the search for maximum funtimes
    $.getJSON("http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q="+search+"+moustache&callback=?",
    function(data){
      $.each(data.responseData.results, function(i,item){
        cb(item.unescapedUrl);
        if ( i == 0 ) return false;
      });
    });
  }

  // TRY ME: Replace this with http://docs.meteor.com/#random
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }
}

<|endoftext|>


<commit_before>
// firebase.database().ref('view').on('value', function(snapshot) {
// 	view = snapshot.val().currentView;
// 	  switch(view) {
// 	       case "/app/checkin/" :
// 	       		//code block
// 	       		showView('.checkin');
// 	       		break;
// 		   case "/app/onboarding/" :
// 		   		//code block
// 		   		showView('.onboarding');
// 		   		break;
// 		   case "/app/decision-are-you-happy/" :
// 		   		showView('.decision-are-you-happy');
// 		   		//code block
// 		   		break;
// 		   case "/app/david-to-life/" :
// 		   		showView('.david-to-life');
//				startHeartbeat();
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-where-david/" :
// 		   		showView('.decision-where-david');
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-reason-for-david-to-move/" :
// 		   		showView('.decision-reason-for-david-to-move');
// 		   		//code block
// 		   		break;
// 		   case "/app/warning/" :
// 		   		showView('.warning');
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-clothing/" :
// 		   		showView('.decision-clothing');
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-emotion/" :
// 		   		showView('.decision-emotion');
// 		   		//code block
// 		   		break;
// 		   case "/app/slider-horizontal/" :
// 		   		showView('.slider-horizontal');
// 		   		//code block
// 		   		break;
// 		   case "/app/slider-vertical/" :
// 		   		showView('.slider-vertical');
// 		   		//code block
// 		   		break;
// 		   case "/app/calculating-results/" :
// 		   		showView('.calculating-results');
// 		   		//code block
// 		   		break;
// 		   case "/app/done/" :
// 		   		showView('.done');
// 		   		//code block
// 		   		break;
// 		   case "/app/percentage-of-vote/" :
// 		   		showView('.percentage-of-vote');
// 		   		//code block
// 		   		break;
// 		   case "/app/pay-attention/" :
// 		   		showView('.pay-attention');
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-want-more/" :
// 		   		showView('.decision-want-more');
// 		   		//code block
// 		   		break;
// 		   case "/app/time-left-with-david/" :
// 		   		showView('.time-left-with-david');
// 		   		//code block
// 		   		break;
// 		   case "/app/decision-are-you-finished/" :
// 		   		showView('.decision-are-you-finished');
// 		   		//code block
// 		   		break;
// 		   case "/app/review-david" :
// 		   		showView('.review-david');
// 		   		//code block
// 		   		break;
// 		   case "/app/review-how-was-david/" :
// 		   		showView('.review-how-was-david');
// 		   		//code block
// 		   		break;
// 		   case "/app/review-would-you-see-david-again/" :
// 		   		showView('.review-would-you-see-david-again');
// 		   		//code block
// 		   		break;
// 		   case "/app/review-thank-you/" :
// 		   		showView('.review-thank-you');
// 		   		//code block
// 		   		break;
// 			default:

// 	}
// });

showView('.david-to-life');
startHeartbeat();

firebase.database().ref('decisions').on('value', function(snapshot){

	// console.log(snapshot.);
	// console.log(snapshot.val());
	// var data = snapshot.exportVal()
	// console.log(data);
	var numberOfNo=0;
	var numberOfYes=0;
	snapshot.forEach(function(data){
		console.log(data.key + ": " +data.val() );
		if(data.val()==="Yes"){
			numberOfYes++;
		}else{
			numberOfNo++;
		}
	});

	console.log("yes:" +numberOfYes);
	if(numberOfYes>numberOfNo){
		$(".decision-are-you-happy-result").html("YES");
	}else{
		$(".decision-are-you-happy-result").html("NO");
	}
});

<commit_msg>easy initialisation<commit_after>// Initialization functions:

function initializeHeartbeat() {
	showView('.david-to-life');
	startHeartbeat();
}

firebase.database().ref('view').on('value', function(snapshot) {
	view = snapshot.val().currentView;
	  switch(view) {
	       case "/app/checkin/" :
	       		//code block
	       		showView('.checkin');
	       		break;
		   case "/app/onboarding/" :
		   		//code block
		   		showView('.onboarding');
		   		break;
		   case "/app/decision-are-you-happy/" :
		   		showView('.decision-are-you-happy');
		   		//code block
		   		break;
		   case "/app/david-to-life/" :
		   		initializeHeartbeat();
		   		//code block
		   		break;
		   case "/app/decision-where-david/" :
		   		showView('.decision-where-david');
		   		//code block
		   		break;
		   case "/app/decision-reason-for-david-to-move/" :
		   		showView('.decision-reason-for-david-to-move');
		   		//code block
		   		break;
		   case "/app/warning/" :
		   		showView('.warning');
		   		//code block
		   		break;
		   case "/app/decision-clothing/" :
		   		showView('.decision-clothing');
		   		//code block
		   		break;
		   case "/app/decision-emotion/" :
		   		showView('.decision-emotion');
		   		//code block
		   		break;
		   case "/app/slider-horizontal/" :
		   		showView('.slider-horizontal');
		   		//code block
		   		break;
		   case "/app/slider-vertical/" :
		   		showView('.slider-vertical');
		   		//code block
		   		break;
		   case "/app/calculating-results/" :
		   		showView('.calculating-results');
		   		//code block
		   		break;
		   case "/app/done/" :
		   		showView('.done');
		   		//code block
		   		break;
		   case "/app/percentage-of-vote/" :
		   		showView('.percentage-of-vote');
		   		//code block
		   		break;
		   case "/app/pay-attention/" :
		   		showView('.pay-attention');
		   		//code block
		   		break;
		   case "/app/decision-want-more/" :
		   		showView('.decision-want-more');
		   		//code block
		   		break;
		   case "/app/time-left-with-david/" :
		   		showView('.time-left-with-david');
		   		//code block
		   		break;
		   case "/app/decision-are-you-finished/" :
		   		showView('.decision-are-you-finished');
		   		//code block
		   		break;
		   case "/app/review-david" :
		   		showView('.review-david');
		   		//code block
		   		break;
		   case "/app/review-how-was-david/" :
		   		showView('.review-how-was-david');
		   		//code block
		   		break;
		   case "/app/review-would-you-see-david-again/" :
		   		showView('.review-would-you-see-david-again');
		   		//code block
		   		break;
		   case "/app/review-thank-you/" :
		   		showView('.review-thank-you');
		   		//code block
		   		break;
			default:

	}
});

firebase.database().ref('decisions').on('value', function(snapshot){

	// console.log(snapshot.);
	// console.log(snapshot.val());
	// var data = snapshot.exportVal()
	// console.log(data);
	var numberOfNo=0;
	var numberOfYes=0;
	snapshot.forEach(function(data){
		console.log(data.key + ": " +data.val() );
		if(data.val()==="Yes"){
			numberOfYes++;
		}else{
			numberOfNo++;
		}
	});

	console.log("yes:" +numberOfYes);
	if(numberOfYes>numberOfNo){
		$(".decision-are-you-happy-result").html("YES");
	}else{
		$(".decision-are-you-happy-result").html("NO");
	}
});

<|endoftext|>


<commit_before>
'use strict';

/* Unit tests for file client/scripts/arcademode/reducers/timer.js. */
import chai, { expect } from 'chai';
import Immutable from 'immutable';

import chaiImmutable from 'chai-immutable';

import reducer, { printTime } from '../../../../..//client/scripts/arcademode/reducers/timer';
import {
  stopTimer,
  actionTimerStarted,
  actionTimerUpdated,
  actionTimerMaxValueChanged,
  actionTimerFinished
//  startTimer
} from '../../../../../client/scripts/arcademode/actions/timer';

import { startChallenge } from '../../../../../client/scripts/arcademode/actions/challenge';

chai.use(chaiImmutable);

const timerDefaultValue = 60 * 1000;

describe('Reducer: timer', () => {
  it('should load max timer on CHALLENGE_START', () => {
    const state = Immutable.Map({
      timerMaxValue: 3000,
      timerMaxValueLoaded: timerDefaultValue
    });
    const nextState = reducer(state, startChallenge(new Date().getTime()));
    expect(nextState).to.equal(Immutable.Map({
      timerMaxValue: 3000,
      timerMaxValueLoaded: 3000
    }));
  });

  it('should stop timer on STOP_TIMER', () => {
    const state = Immutable.Map({
      isTimerFinished: false,
      timeLeft: timerDefaultValue
    });
    const nextState = reducer(state, stopTimer());
    expect(nextState).to.equal(Immutable.Map({
      isTimerFinished: true,
      timeLeft: '00:00'
    }));
  });

  it('should start timer on TIMER_STARTED', () => {
    const state = Immutable.Map({
      isTimerFinished: true,
      // timeLeft: 0,
      timerStart: 123
    });
    const startTime = 0;
    const nextState = reducer(state, actionTimerStarted(startTime));
    expect(nextState).to.equal(Immutable.Map({
      isTimerFinished: false,
      // timeLeft: timerDefaultValue,
      timerStart: startTime
    }));
  });

  it('should update timer on TIMER_UPDATED', () => {
    const state = Immutable.Map({
      timerStart: 0,
      timerMaxValue: timerDefaultValue,
      timeLeft: '01:00'
    });
    const timeNow = 40 * 1000;
    const nextState = reducer(state, actionTimerUpdated(timeNow));
    expect(nextState).to.equal(Immutable.Map({
      timerStart: 0,
      timerMaxValue: timerDefaultValue,
      timeLeft: printTime(state.get('timerMaxValue') - (timeNow - state.get('timerStart')))
    }));
  });

  // no TIMER_FINISHED action; see STOP_TIMER? 5/14/17 add a contrived action for test
  it('should finish timer on TIMER_FINISHED?', () => {
    const state = Immutable.Map({
      isRunningTests: true
    });
    const nextState = reducer(state, actionTimerFinished());
    expect(nextState).to.equal(Immutable.Map({
      isRunningTests: false
    }));
  });

  it('should change max value when TIMER_MAX_VALUE_CHANGED', () => {
    const state = Immutable.Map({
      timerMaxValue: timerDefaultValue
    });
    const userEnteredMaxValue = 30 * 1000;
    const nextState = reducer(state, actionTimerMaxValueChanged(userEnteredMaxValue));
    expect(nextState).to.equal(Immutable.Map({
      timerMaxValue: 30000
    }));
  });
});

<commit_msg>Fixed failing tests.<commit_after>
'use strict';

/* Unit tests for file client/scripts/arcademode/reducers/timer.js. */
import chai, { expect } from 'chai';
import Immutable from 'immutable';

import chaiImmutable from 'chai-immutable';

import reducer, { printTime } from '../../../../..//client/scripts/arcademode/reducers/timer';
import {
  stopTimer,
  actionTimerStarted,
  actionTimerUpdated,
  actionTimerMaxValueChanged,
  actionTimerFinished
//  startTimer
} from '../../../../../client/scripts/arcademode/actions/timer';

import { startChallenge } from '../../../../../client/scripts/arcademode/actions/challenge';

chai.use(chaiImmutable);

const timerDefaultValue = 60 * 1000;

describe('Reducer: timer', () => {
  it('should load max timer on CHALLENGE_START', () => {
    const state = Immutable.Map({
      timerMaxValue: 3000,
      timerMaxValueLoaded: timerDefaultValue
    });
    const nextState = reducer(state, startChallenge(new Date().getTime()));
    expect(nextState).to.equal(Immutable.Map({
      timerMaxValue: 3000,
      timerMaxValueLoaded: 3000
    }));
  });

  it('should stop timer on STOP_TIMER', () => {
    const state = Immutable.Map({
      isTimerFinished: false,
      timeLeft: timerDefaultValue
    });
    const nextState = reducer(state, stopTimer());
    expect(nextState).to.equal(Immutable.Map({
      isTimerFinished: true,
      timeLeft: '00:00'
    }));
  });

  it('should start timer on TIMER_STARTED', () => {
    const state = Immutable.Map({
      isTimerFinished: true,
      // timeLeft: 0,
      timerStart: 123
    });
    const startTime = 0;
    const nextState = reducer(state, actionTimerStarted(startTime));
    expect(nextState).to.equal(Immutable.Map({
      isTimerFinished: false,
      // timeLeft: timerDefaultValue,
      timerStart: startTime
    }));
  });

  it('should update timer on TIMER_UPDATED', () => {
    const state = Immutable.Map({
      timerStart: 0,
      timerMaxValue: timerDefaultValue,
      timeLeft: '01:00'
    });
    const timeNow = 40 * 1000;
    const nextState = reducer(state, actionTimerUpdated(timeNow));
    expect(nextState).to.equal(Immutable.Map({
      timerStart: 0,
      timerMaxValue: timerDefaultValue,
      timeLeft: printTime(state.get('timerMaxValue') - (timeNow - state.get('timerStart'))),
      timeUsed: '00:40'
    }));
  });

  it('should finish timer on TIMER_FINISHED', () => {
    const state = Immutable.Map({
      isTimerFinished: false
    });
    const nextState = reducer(state, actionTimerFinished());
    expect(nextState).to.equal(Immutable.Map({
      isTimerFinished: true,
      timeLeft: '00:00'
    }));
  });

  it('should change max value when TIMER_MAX_VALUE_CHANGED', () => {
    const state = Immutable.Map({
      timerMaxValue: timerDefaultValue
    });
    const userEnteredMaxValue = 30 * 1000;
    const nextState = reducer(state, actionTimerMaxValueChanged(userEnteredMaxValue));
    expect(nextState).to.equal(Immutable.Map({
      timerMaxValue: 30000
    }));
  });
});

<|endoftext|>


<commit_before>var Like = function () {
    var likeUrl = $('#like-url').val();

    var updateLikesCount = function (link, count) {
        link.find('span').html(count);
    };

    var disableLinks = function () {
        $('.like-job').each(function () {
            $(this).data('canlike', false);
            $(this).addClass('disabled');
        });
    };

    return {
        performLike: function (e) {
            e.preventDefault();

            var $link = $(e.currentTarget);

            if (!$link.data('canlike')) return;

            var like = $link.data('like');

            var antiForgeryToken = $("input[name=__RequestVerificationToken]").val();

            var req = $.post(likeUrl, { jobOpportunityId: $link.data('job'), like: like, __RequestVerificationToken: antiForgeryToken });

            req.success(function (response, textStatus, request) {
                console.log(textStatus);
                console.log(request);
                var header = request.getResponseHeader("X-Responded-JSON");
                console.log(header);
                if (typeof(header) !== 'undefined') {
                    var headerJson = JSON.parse(header);
                    if (headerJson.status == "401") {
                        alert("Debes iniciar sesion para poder dar like a los empleos");
                    }
                }else{
                    updateLikesCount($link, (like ? response.data.Likes : response.data.DisLikes));
                    disableLinks();
                }
            });
            console.log(req);
            req.fail(function (response) {
                // TODO: Find a better way to show this message.
                alert("Ha ocurrido un error, disculpa los inconvenientes");
            });
        }
    };
};

(function () {
    var like = new Like();

    $('.like-job').click(function (e) { like.performLike(e); });
})();<commit_msg>Fixed bug with Like Button (#531) Bug fixed and the default alert was changed by sweetalert.<commit_after>var Like = function () {
    var likeUrl = $('#like-url').val();

    var updateLikesCount = function (link, count) {
        link.find('span').html(count);
    };

    var disableLinks = function () {
        $('.like-job').each(function () {
            $(this).data('canlike', false);
            $(this).addClass('disabled');
        });
    };

    return {
        performLike: function (e) {
            e.preventDefault();

            var $link = $(e.currentTarget);

            if (!$link.data('canlike')) return;

            var like = $link.data('like');

            var antiForgeryToken = $("input[name=__RequestVerificationToken]").val();

            var req = $.post(likeUrl, { jobOpportunityId: $link.data('job'), like: like, __RequestVerificationToken: antiForgeryToken });

            req.success(function (response, textStatus, request) {
                var header = request.getResponseHeader("X-Responded-JSON");

                if (typeof(header) !== 'undefined') {
                    var headerJson = JSON.parse(header);
                    if (!$.isEmptyObject(headerJson) && headerJson.status == "401") {
                        // SweetAlert replacing default alert
                        swal('','Debes iniciar sesion para poder dar like a los empleos','warning');
                    } else if (!$.isEmptyObject(response) && !response.error ) {
                        updateLikesCount($link, (like ? response.data.Likes : response.data.DisLikes));
                        disableLinks();
                    }
                }else{
                    updateLikesCount($link, (like ? response.data.Likes : response.data.DisLikes));
                    disableLinks();
                }
            });

            req.fail(function (response) {
                if (typeof (response) !== 'undefined' && response.error) {
                    swal('', response.message, 'error');
                } else {
                    swal('Oops...','Ha ocurrido un error, disculpa los inconvenientes','error');
                }
            });
        }
    };
};

(function () {
    var like = new Like();

    $('.like-job').click(function (e) { like.performLike(e); });
})();<|endoftext|>


<commit_before>/* jshint newcap: false */
(function() {
	"use strict";

	/**
	 * Voyeur "constructor". Never initilize with the new keyword.
	 * @param {HTMLElement|Array of elements} nodes Array of nodes to create a Voyeur object with
	 * @return {Voyeur} Voyeur extended Node
	 */
	var Voyeur = function(nodes) {
		if(nodes instanceof HTMLElement) {
			//Single node so extend it's children
			Voyeur.extendChildren(nodes);
		}

		//Create the `create` instance
		nodes.create = Voyeur.extendTags({}, function(tag) {
			return Voyeur.create.bind({
				tag: tag,
				parents: nodes
			})();
		});

		/**
		 * Use the current scope
		 * @param  {Function} fn The callback function with the current scope sent as parameter
		 * @return {Voyeur}      The root node
		 */
		nodes.use = function(fn) {
			if(fn) {
				if(nodes instanceof Array) {
					nodes.forEach(function(elem, i) {
						fn.call(window, Voyeur(elem), i);
					});
				} else {
					fn.call(window, nodes);
				}
			}

			return nodes.root;
		};

		/**
		 * Find via selector inside the current scope
		 * @param  {String} selector The selector
		 * @return {Voyeur}          The new Voyeur object
		 */
		nodes.find = function(selector) {
			var children;
			if(nodes instanceof Array) {
				children = [];
				nodes.forEach(function(node) {
					children = children.concat(Array.prototype.slice.call(node.querySelectorAll(selector)));
				});
			} else {
				children = Array.prototype.slice.call(nodes.querySelectorAll(selector));
			}

			if(children.length) {
				return Voyeur(children.length === 1 ? children[0] : children);
			}
		};

		/**
		 * Select part of an array
		 * @param  {number} u The start index
		 * @param  {number} v The end index (optional)
		 * @return {Voyeur}   The selected nodes
		 */
		nodes.eq = function(u, v) {
			if(nodes instanceof Array) {
				var newNodes = nodes.slice(u, v || (u + 1));
				return Voyeur(newNodes.length === 1 ? newNodes[0] : newNodes);
			} else {
				return nodes;
			}
		};

		return nodes;
	};

	/**
	 * Extends a node's children unto it
	 * @param  {Object} node  The node to extend it's children unto
	 * @param {Array} children An array of children to expand to
	 * @return {Object}      The object extended
	 */
	Voyeur.extendChildren = function(node, children) {
		children = Array.prototype.slice.call(children || node.children);

		//The tag map
		var map = {};

		for(var i = children.length - 1; i >= 0; i--) {
			var child = children[i],
				tag = child.tagName.toLowerCase();

			if(!map[tag]) {
				map[tag] = [];
			}
			map[tag].push(child);
		}

		/* jshint loopfunc: true */
		for(var key in map) {
			(function(key) { //Closure required
				Object.defineProperty(node, key, {
					get: function() {
						return Voyeur(map[key].length === 1 ? map[key][0] : map[key]);
					},

					configurable: true
				});
			})(key);
		}
	};

	/**
	 * Voyeur.create recursive function
	 * @param  {Array|HTMLElement} parents The array of parents|htmlelement
	 * @return {Object}         A create object
	 */
	Voyeur.create = function(parents) {
		var self = parents || Voyeur.createElement(this.parents, this.tag);
		self.root = this.root || self;
		self.parents = this.parents;

		Voyeur.extendTags(self, function(tag) {
			Voyeur.unextendTags(self);

			return Voyeur.create.bind({
				root: self.root,
				parents: self,
				tag: tag
			})();
		});

		self.use = function(fn) {
			if(fn) {
				if(self instanceof Array) {
					self.forEach(function(elem, i) {
						elem = Voyeur(elem);
						fn.call(elem, elem, i);
					});
				} else {
					var vSelf = Voyeur(self);
					fn.call(vSelf, vSelf);
				}
			}

			Voyeur.unextendTags(self.root);

			return Voyeur(self.root);
		};

		self.mult = function(factor) {
			//Get rid of the inital node
			self.parentNode.removeChild(self);

			var elems = [];
			for(var i = 0; i < factor; i++) {
				var elem = Voyeur.createElement(self.parents, self.tagName.toLowerCase());
				elems.push(elem);
			}
			return Voyeur.create.bind({
				root: self.root
			})(elems);
		};

		self.special = function(tag) {
			return Voyeur.create.bind({
				root: self.root,
				parents: self,
				tag: tag
			})();
		};

		return self;

	};

	/**
	 * Create an element and insert it into parents if passed
	 * @param  {Array|HTMLElement} parents Parent(s) to insert into (optional)
	 * @param  {String} tag     The HTML element tag
	 * @return {Array|HTMLElement}         The array of new parents or element
	 */
	Voyeur.createElement = function(parents, tag) {

		// helper
		function create() {
			return document.createElement(tag);
		}

		if(parents) {
			if(parents instanceof Array) {
				var newParents = [];
				parents.forEach(function(mummy) {
					var elem = create();
					mummy.appendChild(elem);
					newParents.push(elem);
				});

				return newParents;
			} else {
				var elem = create();
				parents.appendChild(elem);
				return elem;
			}
		} else {
			return create();
		}

	};

	Voyeur.nodes = "a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,br,button,canvas,caption,center,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dir,div,dl,dt,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,i,iframe,img,input,ins,isindex,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,menu,menuitem,meta,meter,nav,nobr,noframes,noscript,object,ol,optgroup,option,output,p,param,plaintext,pre,progress,q,rp,rt,ruby,s,samp,section,select,small,source,spacer,span,strike,strong,sub,summary,sup,table,tbody,td,textarea,tfoot,th,thead,time,tr,track,tt,u,ul,var,video,wbr,xmp".split(",");

	/**
	 * Extends all of the Voyeur.nodes tags onto an object via a getter
	 * @param  {Object}   obj The reciever object
	 * @param  {Function} fn  The function on get with `tag` sent to it
	 * @return {Object}       The reciever object
	 */
	Voyeur.extendTags = function(obj, fn) {
		Voyeur.nodes.forEach(function(tag) {
			Object.defineProperty(obj, tag, {
				get: function() {
					return fn.call(obj, tag);
				},

				configurable: true
			});
		});

		return obj;
	};

	Voyeur.unextendTags = function(obj) {
		Voyeur.nodes.forEach(function(tag) {
			delete obj[tag];
		});

		return obj;
	};

	document.addEventListener("DOMContentLoaded", function() {
		//Initilize Voyeur on the document
		window.Voyeur = Voyeur(document.body);

		//Create for the root Voyeur
		window.Voyeur.create = Voyeur.extendTags({}, function(tag) {
			return Voyeur.create.bind({
				tag: tag
			})();
		});

		//Special create function
		window.Voyeur.create.special = function(tag) {
			return Voyeur.create.bind({
				tag: tag
			})();
		};
	});
})();<commit_msg>Running .use in the context of the the node<commit_after>/* jshint newcap: false */
(function() {
	"use strict";

	/**
	 * Voyeur "constructor". Never initilize with the new keyword.
	 * @param {HTMLElement|Array of elements} nodes Array of nodes to create a Voyeur object with
	 * @return {Voyeur} Voyeur extended Node
	 */
	var Voyeur = function(nodes) {
		if(nodes instanceof HTMLElement) {
			//Single node so extend it's children
			Voyeur.extendChildren(nodes);
		}

		//Create the `create` instance
		nodes.create = Voyeur.extendTags({}, function(tag) {
			return Voyeur.create.bind({
				tag: tag,
				parents: nodes
			})();
		});

		/**
		 * Use the current scope
		 * @param  {Function} fn The callback function with the current scope sent as parameter
		 * @return {Voyeur}      The root node
		 */
		nodes.use = function(fn) {
			if(fn) {
				if(nodes instanceof Array) {
					nodes.forEach(function(elem, i) {
						var elem = Voyeur(elem);
						fn.call(elem, elem, i);
					});
				} else {
					fn.call(nodes, nodes);
				}
			}

			return nodes.root;
		};

		/**
		 * Find via selector inside the current scope
		 * @param  {String} selector The selector
		 * @return {Voyeur}          The new Voyeur object
		 */
		nodes.find = function(selector) {
			var children;
			if(nodes instanceof Array) {
				children = [];
				nodes.forEach(function(node) {
					children = children.concat(Array.prototype.slice.call(node.querySelectorAll(selector)));
				});
			} else {
				children = Array.prototype.slice.call(nodes.querySelectorAll(selector));
			}

			if(children.length) {
				return Voyeur(children.length === 1 ? children[0] : children);
			}
		};

		/**
		 * Select part of an array
		 * @param  {number} u The start index
		 * @param  {number} v The end index (optional)
		 * @return {Voyeur}   The selected nodes
		 */
		nodes.eq = function(u, v) {
			if(nodes instanceof Array) {
				var newNodes = nodes.slice(u, v || (u + 1));
				return Voyeur(newNodes.length === 1 ? newNodes[0] : newNodes);
			} else {
				return nodes;
			}
		};

		return nodes;
	};

	/**
	 * Extends a node's children unto it
	 * @param  {Object} node  The node to extend it's children unto
	 * @param {Array} children An array of children to expand to
	 * @return {Object}      The object extended
	 */
	Voyeur.extendChildren = function(node, children) {
		children = Array.prototype.slice.call(children || node.children);

		//The tag map
		var map = {};

		for(var i = children.length - 1; i >= 0; i--) {
			var child = children[i],
				tag = child.tagName.toLowerCase();

			if(!map[tag]) {
				map[tag] = [];
			}
			map[tag].push(child);
		}

		/* jshint loopfunc: true */
		for(var key in map) {
			(function(key) { //Closure required
				Object.defineProperty(node, key, {
					get: function() {
						return Voyeur(map[key].length === 1 ? map[key][0] : map[key]);
					},

					configurable: true
				});
			})(key);
		}
	};

	/**
	 * Voyeur.create recursive function
	 * @param  {Array|HTMLElement} parents The array of parents|htmlelement
	 * @return {Object}         A create object
	 */
	Voyeur.create = function(parents) {
		var self = parents || Voyeur.createElement(this.parents, this.tag);
		self.root = this.root || self;
		self.parents = this.parents;

		Voyeur.extendTags(self, function(tag) {
			Voyeur.unextendTags(self);

			return Voyeur.create.bind({
				root: self.root,
				parents: self,
				tag: tag
			})();
		});

		self.use = function(fn) {
			if(fn) {
				if(self instanceof Array) {
					self.forEach(function(elem, i) {
						elem = Voyeur(elem);
						fn.call(elem, elem, i);
					});
				} else {
					var vSelf = Voyeur(self);
					fn.call(vSelf, vSelf);
				}
			}

			Voyeur.unextendTags(self.root);

			return Voyeur(self.root);
		};

		self.mult = function(factor) {
			//Get rid of the inital node
			self.parentNode.removeChild(self);

			var elems = [];
			for(var i = 0; i < factor; i++) {
				var elem = Voyeur.createElement(self.parents, self.tagName.toLowerCase());
				elems.push(elem);
			}
			return Voyeur.create.bind({
				root: self.root
			})(elems);
		};

		self.special = function(tag) {
			return Voyeur.create.bind({
				root: self.root,
				parents: self,
				tag: tag
			})();
		};

		return self;

	};

	/**
	 * Create an element and insert it into parents if passed
	 * @param  {Array|HTMLElement} parents Parent(s) to insert into (optional)
	 * @param  {String} tag     The HTML element tag
	 * @return {Array|HTMLElement}         The array of new parents or element
	 */
	Voyeur.createElement = function(parents, tag) {

		// helper
		function create() {
			return document.createElement(tag);
		}

		if(parents) {
			if(parents instanceof Array) {
				var newParents = [];
				parents.forEach(function(mummy) {
					var elem = create();
					mummy.appendChild(elem);
					newParents.push(elem);
				});

				return newParents;
			} else {
				var elem = create();
				parents.appendChild(elem);
				return elem;
			}
		} else {
			return create();
		}

	};

	Voyeur.nodes = "a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,br,button,canvas,caption,center,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dir,div,dl,dt,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,i,iframe,img,input,ins,isindex,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,menu,menuitem,meta,meter,nav,nobr,noframes,noscript,object,ol,optgroup,option,output,p,param,plaintext,pre,progress,q,rp,rt,ruby,s,samp,section,select,small,source,spacer,span,strike,strong,sub,summary,sup,table,tbody,td,textarea,tfoot,th,thead,time,tr,track,tt,u,ul,var,video,wbr,xmp".split(",");

	/**
	 * Extends all of the Voyeur.nodes tags onto an object via a getter
	 * @param  {Object}   obj The reciever object
	 * @param  {Function} fn  The function on get with `tag` sent to it
	 * @return {Object}       The reciever object
	 */
	Voyeur.extendTags = function(obj, fn) {
		Voyeur.nodes.forEach(function(tag) {
			Object.defineProperty(obj, tag, {
				get: function() {
					return fn.call(obj, tag);
				},

				configurable: true
			});
		});

		return obj;
	};

	Voyeur.unextendTags = function(obj) {
		Voyeur.nodes.forEach(function(tag) {
			delete obj[tag];
		});

		return obj;
	};

	document.addEventListener("DOMContentLoaded", function() {
		//Initilize Voyeur on the document
		window.Voyeur = Voyeur(document.body);

		//Create for the root Voyeur
		window.Voyeur.create = Voyeur.extendTags({}, function(tag) {
			return Voyeur.create.bind({
				tag: tag
			})();
		});

		//Special create function
		window.Voyeur.create.special = function(tag) {
			return Voyeur.create.bind({
				tag: tag
			})();
		};
	});
})();<|endoftext|>


<commit_before>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';
import HIT_TYPES from "Parser/Core/HIT_TYPES";
import Combatants from "Parser/Core/Modules/Combatants";

import SPELLS from "common/SPELLS/HUNTER";
import TALENTS from 'common/SPELLS/TALENTS/HUNTER';
import StatisticBox, { STATISTIC_ORDER } from 'Main/StatisticBox';
import SpellLink from "common/SpellLink";
import SpellIcon from "common/SpellIcon";
import Icon from "common/Icon";
import { formatNumber, formatPercentage } from "common/format";
import RESOURCE_TYPES from 'common/RESOURCE_TYPES';

class Trueshot extends Analyzer {
  static dependencies = {
    combatants: Combatants,
  };

  trueshotCasts = 0;
  accumulatedFocusAtTSCast = 0;
  aimedShotsPrTS = 0;
  aimedCritsInTS = 0;
  totalCritsInTS = 0;
  totalCastsPrTS = 0;
  executeTrueshots = 0;
  startFocusForCombatant = 0;
  prepullTrueshots = 0;

  on_byPlayer_applybuff(event) {
    const buffId = event.ability.guid;
    if (buffId !== SPELLS.TRUESHOT.id && !event.prepull) {
      return;
    }
    //ensures we only get 1 of these events
    if (this.trueshotCasts === 0) {
      //adds 1 to trueshotCasts to properly show that it was cast prepull
      this.trueshotCasts += 1;
      this.prepullTrueshots += 1;
    }
  }

  on_byPlayer_cast(event) {
//checks if we had a prepull trueshot, in which case the firstCast done symbolises our starting focus of that one trueshot
    if (this.prepullTrueshots > 0 && this.startFocusForCombatant === 0) {
      event.classResources.forEach(classResource => {
        if (classResource.type === RESOURCE_TYPES.FOCUS && classResource['amount'] > this.startFocusForCombatant) {
          this.startFocusForCombatant += classResource['amount'];
          this.accumulatedFocusAtTSCast += this.startFocusForCombatant;
        }
      });
    }
    const buffId = event.ability.guid;
    if (buffId === SPELLS.TRUESHOT.id) {
      this.trueshotCasts += 1;
      this.accumulatedFocusAtTSCast += event.classResources[0]['amount'] || 0;
      if (this.combatants.selected.hasBuff(SPELLS.BULLSEYE_TRAIT.id, event.timestamp)) {
        this.executeTrueshots += 1;
      }
    }
    const trueshotUptime = this.combatants.getBuffUptime(SPELLS.TRUESHOT.id);
    if (trueshotUptime > 0 && this.trueshotCasts === 0) {
      this.trueshotCasts += 1;
    }
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    const isCrit = event.hitType === HIT_TYPES.CRIT;

    if (!this.combatants.selected.hasBuff(SPELLS.TRUESHOT.id, event.timestamp)) {
      return;
    }
    this.totalCastsPrTS += 1;
    if (isCrit) {
      this.totalCritsInTS += 1;
      if (spellId === SPELLS.AIMED_SHOT.id) {
        this.aimedCritsInTS += 1;
      }
    }
    if (spellId !== SPELLS.AIMED_SHOT.id) {
      return;
    }
    this.aimedShotsPrTS += 1;

  }

  statistic() {
    const averageAimedCasts = formatNumber(this.aimedShotsPrTS / this.trueshotCasts);
    const averageFocusAtTS = formatNumber(this.accumulatedFocusAtTSCast / this.trueshotCasts);
    const percentAimedCrits = formatPercentage(this.aimedCritsInTS / this.aimedShotsPrTS);
    const percentCastCrits = formatPercentage(this.totalCritsInTS / this.totalCastsPrTS);
    const uptimePrCast = ((this.combatants.getBuffUptime(SPELLS.TRUESHOT.id) / this.trueshotCasts) / 1000).toFixed(2);

    return (
      <StatisticBox icon={<SpellIcon id={SPELLS.TRUESHOT.id} />}
        value={(

            {averageAimedCasts}{' '}
            <SpellIcon
              id={SPELLS.AIMED_SHOT.id}
              style={{
                height: '1.3em',
                marginTop: '-.1em',
              }}
            />
            {'  '}
            {averageFocusAtTS}{' '}
            <Icon
              icon='ability_hunter_focusfire'
              alt='Average Focus At Trueshot Cast'
              style={{
                height: '1.3em',
                marginTop: '-.1em',
              }}
            />

        )}
        label={'Trueshot info'}
        tooltip={`Information regarding your average Trueshot window:

You started your Trueshot windows with an average of ${averageFocusAtTS} focus.

 You hit an average of ${averageAimedCasts} Aimed Shots inside each Trueshot window.

 Your Trueshot Aimed Shots had a crit rate of ${percentAimedCrits}%.

Your overall crit rate during Trueshot was ${percentCastCrits}%.

You spent an average of ${uptimePrCast} seconds in trueshot pr cast of Trueshot.

`} />
    );
  }

  suggestions(when) {
    const averageAimedCasts = formatNumber(this.aimedShotsPrTS / this.trueshotCasts);
    const averageFocusAtTS = formatNumber(this.accumulatedFocusAtTSCast / this.trueshotCasts);
    const uptimePrCast = ((this.combatants.getBuffUptime(SPELLS.TRUESHOT.id) / this.trueshotCasts) / 1000).toFixed(2);
    when(averageAimedCasts).isLessThan(8)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You only cast {averageAimedCasts} <SpellLink id={SPELLS.AIMED_SHOT.id} />s inside your average <SpellLink id={SPELLS.TRUESHOT.id} /> window. This is your only DPS cooldown, and it's important to maximize it to it's fullest potential by getting as many Aimed Shot squeezed in as possible, while still making sure that they are all within <SpellLink id={SPELLS.VULNERABLE.id} />.
 This can be done by making sure to use <SpellLink id={SPELLS.WINDBURST.id} /> to open <SpellLink id={SPELLS.VULNERABLE.id} /> windows, not using <SpellLink id={TALENTS.A_MURDER_OF_CROWS_TALENT_SHARED.id} /> while in <SpellLink id={SPELLS.TRUESHOT.id} /> or starting <SpellLink id={SPELLS.TRUESHOT.id} /> at higher focus. )
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`Average of ${averageAimedCasts} Aimed Shots pr Trueshot.`)
          .recommended(`>${recommended} is recommended`)
          //to make sure that if we go 1 cast below the recommended, it shows up as average, or 2 as major.
          .regular(recommended - 0.9)
          .major(recommended - 1.9);
      });
    when(averageFocusAtTS).isLessThan(90)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You started your average <SpellLink id={SPELLS.TRUESHOT.id} /> at {averageFocusAtTS} focus, try and pool a bit more before casting <SpellLink id={SPELLS.TRUESHOT.id} />. This can be done through casting an additional <SpellLink id={SPELLS.ARCANE_SHOT.id} /> or by monitoring the cooldown of <SpellLink id={SPELLS.TRUESHOT.id} /> and adjusting play to ensure your focus won't be depleted when it comes off cooldown.)
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`Average of ${averageFocusAtTS > 0 ? averageFocusAtTS : this.startFocusForCombatant} focus when starting Trueshot`)
          .recommended(`>${recommended} is recommended`)
          .regular(recommended - 10)
          .major(recommended - 20);
      });
    when(this.executeTrueshots).isLessThan(1)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You should make sure to have atleast 1 <SpellLink id={SPELLS.TRUESHOT.id} /> cast during execute (where you are buffed by <SpellLink id={SPELLS.BULLSEYE_TRAIT.id} />) to get as much out of <SpellLink id={SPELLS.TRUESHOT.id} /> as possible.)
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`You had ${this.executeTrueshots} trueshot casts during Bullseye`)
          .recommended(`casting atleast 1 trueshot in execute is recommended`)
          .major(recommended);
      });
    when(uptimePrCast).isLessThan(15)
      .addSuggestion((suggest, actual, recommended) => {
      return suggest(You should make sure to utilise every possible second of <SpellLink id={SPELLS.TRUESHOT.id}/> uptime as you can. Remember to cast it atleast 15 seconds before the boss dies, so you don't lose out on valuable time, aswell as remember to not cast it until the boss has been engaged.)
        .icon(SPELLS.TRUESHOT.icon)
        .actual(`You had an average of ${uptimePrCast} seconds of trueshot uptime per cast`)
        .recommended(`${recommended} seconds uptime per cast is recommended`)
        .regular(recommended-0.1)
        .major(recommended-0.5);
      });
  }
  statisticOrder = STATISTIC_ORDER.CORE(8);
}

export default Trueshot;
<commit_msg>capitalization<commit_after>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';
import HIT_TYPES from "Parser/Core/HIT_TYPES";
import Combatants from "Parser/Core/Modules/Combatants";

import SPELLS from "common/SPELLS/HUNTER";
import TALENTS from 'common/SPELLS/TALENTS/HUNTER';
import StatisticBox, { STATISTIC_ORDER } from 'Main/StatisticBox';
import SpellLink from "common/SpellLink";
import SpellIcon from "common/SpellIcon";
import Icon from "common/Icon";
import { formatNumber, formatPercentage } from "common/format";
import RESOURCE_TYPES from 'common/RESOURCE_TYPES';

class Trueshot extends Analyzer {
  static dependencies = {
    combatants: Combatants,
  };

  trueshotCasts = 0;
  accumulatedFocusAtTSCast = 0;
  aimedShotsPrTS = 0;
  aimedCritsInTS = 0;
  totalCritsInTS = 0;
  totalCastsPrTS = 0;
  executeTrueshots = 0;
  startFocusForCombatant = 0;
  prepullTrueshots = 0;

  on_byPlayer_applybuff(event) {
    const buffId = event.ability.guid;
    if (buffId !== SPELLS.TRUESHOT.id && !event.prepull) {
      return;
    }
    //ensures we only get 1 of these events
    if (this.trueshotCasts === 0) {
      //adds 1 to trueshotCasts to properly show that it was cast prepull
      this.trueshotCasts += 1;
      this.prepullTrueshots += 1;
    }
  }

  on_byPlayer_cast(event) {
//checks if we had a prepull trueshot, in which case the firstCast done symbolises our starting focus of that one trueshot
    if (this.prepullTrueshots > 0 && this.startFocusForCombatant === 0) {
      event.classResources.forEach(classResource => {
        if (classResource.type === RESOURCE_TYPES.FOCUS && classResource['amount'] > this.startFocusForCombatant) {
          this.startFocusForCombatant += classResource['amount'];
          this.accumulatedFocusAtTSCast += this.startFocusForCombatant;
        }
      });
    }
    const buffId = event.ability.guid;
    if (buffId === SPELLS.TRUESHOT.id) {
      this.trueshotCasts += 1;
      this.accumulatedFocusAtTSCast += event.classResources[0]['amount'] || 0;
      if (this.combatants.selected.hasBuff(SPELLS.BULLSEYE_TRAIT.id, event.timestamp)) {
        this.executeTrueshots += 1;
      }
    }
    const trueshotUptime = this.combatants.getBuffUptime(SPELLS.TRUESHOT.id);
    if (trueshotUptime > 0 && this.trueshotCasts === 0) {
      this.trueshotCasts += 1;
    }
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    const isCrit = event.hitType === HIT_TYPES.CRIT;

    if (!this.combatants.selected.hasBuff(SPELLS.TRUESHOT.id, event.timestamp)) {
      return;
    }
    this.totalCastsPrTS += 1;
    if (isCrit) {
      this.totalCritsInTS += 1;
      if (spellId === SPELLS.AIMED_SHOT.id) {
        this.aimedCritsInTS += 1;
      }
    }
    if (spellId !== SPELLS.AIMED_SHOT.id) {
      return;
    }
    this.aimedShotsPrTS += 1;

  }

  statistic() {
    const averageAimedCasts = formatNumber(this.aimedShotsPrTS / this.trueshotCasts);
    const averageFocusAtTS = formatNumber(this.accumulatedFocusAtTSCast / this.trueshotCasts);
    const percentAimedCrits = formatPercentage(this.aimedCritsInTS / this.aimedShotsPrTS);
    const percentCastCrits = formatPercentage(this.totalCritsInTS / this.totalCastsPrTS);
    const uptimePrCast = ((this.combatants.getBuffUptime(SPELLS.TRUESHOT.id) / this.trueshotCasts) / 1000).toFixed(2);

    return (
      <StatisticBox icon={<SpellIcon id={SPELLS.TRUESHOT.id} />}
        value={(

            {averageAimedCasts}{' '}
            <SpellIcon
              id={SPELLS.AIMED_SHOT.id}
              style={{
                height: '1.3em',
                marginTop: '-.1em',
              }}
            />
            {'  '}
            {averageFocusAtTS}{' '}
            <Icon
              icon='ability_hunter_focusfire'
              alt='Average Focus At Trueshot Cast'
              style={{
                height: '1.3em',
                marginTop: '-.1em',
              }}
            />

        )}
        label={'Trueshot info'}
        tooltip={`Information regarding your average Trueshot window:

You started your Trueshot windows with an average of ${averageFocusAtTS} focus.

 You hit an average of ${averageAimedCasts} Aimed Shots inside each Trueshot window.

 Your Trueshot Aimed Shots had a crit rate of ${percentAimedCrits}%.

Your overall crit rate during Trueshot was ${percentCastCrits}%.

You spent an average of ${uptimePrCast} seconds in trueshot pr cast of Trueshot.

`} />
    );
  }

  suggestions(when) {
    const averageAimedCasts = formatNumber(this.aimedShotsPrTS / this.trueshotCasts);
    const averageFocusAtTS = formatNumber(this.accumulatedFocusAtTSCast / this.trueshotCasts);
    const uptimePrCast = ((this.combatants.getBuffUptime(SPELLS.TRUESHOT.id) / this.trueshotCasts) / 1000).toFixed(2);
    when(averageAimedCasts).isLessThan(8)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You only cast {averageAimedCasts} <SpellLink id={SPELLS.AIMED_SHOT.id} />s inside your average <SpellLink id={SPELLS.TRUESHOT.id} /> window. This is your only DPS cooldown, and it's important to maximize it to it's fullest potential by getting as many Aimed Shot squeezed in as possible, while still making sure that they are all within <SpellLink id={SPELLS.VULNERABLE.id} />.
 This can be done by making sure to use <SpellLink id={SPELLS.WINDBURST.id} /> to open <SpellLink id={SPELLS.VULNERABLE.id} /> windows, not using <SpellLink id={TALENTS.A_MURDER_OF_CROWS_TALENT_SHARED.id} /> while in <SpellLink id={SPELLS.TRUESHOT.id} /> or starting <SpellLink id={SPELLS.TRUESHOT.id} /> at higher focus. )
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`Average of ${averageAimedCasts} Aimed Shots pr Trueshot.`)
          .recommended(`>${recommended} is recommended`)
          //to make sure that if we go 1 cast below the recommended, it shows up as average, or 2 as major.
          .regular(recommended - 0.9)
          .major(recommended - 1.9);
      });
    when(averageFocusAtTS).isLessThan(90)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You started your average <SpellLink id={SPELLS.TRUESHOT.id} /> at {averageFocusAtTS} focus, try and pool a bit more before casting <SpellLink id={SPELLS.TRUESHOT.id} />. This can be done through casting an additional <SpellLink id={SPELLS.ARCANE_SHOT.id} /> or by monitoring the cooldown of <SpellLink id={SPELLS.TRUESHOT.id} /> and adjusting play to ensure your focus won't be depleted when it comes off cooldown.)
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`Average of ${averageFocusAtTS > 0 ? averageFocusAtTS : this.startFocusForCombatant} focus when starting Trueshot`)
          .recommended(`>${recommended} is recommended`)
          .regular(recommended - 10)
          .major(recommended - 20);
      });
    when(this.executeTrueshots).isLessThan(1)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(You should make sure to have atleast 1 <SpellLink id={SPELLS.TRUESHOT.id} /> cast during execute (where you are buffed by <SpellLink id={SPELLS.BULLSEYE_TRAIT.id} />) to get as much out of <SpellLink id={SPELLS.TRUESHOT.id} /> as possible.)
          .icon(SPELLS.TRUESHOT.icon)
          .actual(`You had ${this.executeTrueshots} trueshot casts during Bullseye`)
          .recommended(`casting atleast 1 trueshot in execute is recommended`)
          .major(recommended);
      });
    when(uptimePrCast).isLessThan(15)
      .addSuggestion((suggest, actual, recommended) => {
      return suggest(You should make sure to utilise every possible second of <SpellLink id={SPELLS.TRUESHOT.id}/> uptime as you can. Remember to cast it atleast 15 seconds before the boss dies, so you don't lose out on valuable time, aswell as remember to not cast it until the boss has been engaged.)
        .icon(SPELLS.TRUESHOT.icon)
        .actual(`You had an average of ${uptimePrCast} seconds of Trueshot uptime per cast`)
        .recommended(`${recommended} seconds uptime per cast is recommended`)
        .regular(recommended-0.1)
        .major(recommended-0.5);
      });
  }
  statisticOrder = STATISTIC_ORDER.CORE(8);
}

export default Trueshot;
<|endoftext|>


<commit_before>/*
Constructors for SCXML events, since the browser's built-in DOM Events
are not ideally suited for that role.
*/

// the basic constructor:
SCxml.Event=function SCxmlEvent(name, type)
{
	this.name=name
	this.timestamp=new Date().getTime()
	this.type=type||"platform"
}

SCxml.Event.prototype.toString=function ()
{ return "SCxmlEvent("+this.name+")" }
SCxml.Event.prototype.match=function (t)
// matches transitions and events, e.g. "user.*" matches "user.login"
// the argument is an actual <transtion> element
{
	var patterns=t.getAttribute("event").split(/\s+/)
	var event=this.name.split(".")

	overPatterns: for(var i=0, p; p=patterns[i]; i++)
	{
		if((p=p.split(".")).length>event.length) continue
		for(var j=0; j<p.length; j++)
			if(p[j]!="*" && p[j]!=event[j]) continue overPatterns
		return true
	}
	return false
}

// sub-constructors for internal, error and external events:

SCxml.InternalEvent=function (name, src)
{
	SCxml.Event.call(this, name, "internal")
	this.srcElement=src||null
}
SCxml.InternalEvent.prototype=new SCxml.Event()
SCxml.InternalEvent.prototype.constructor=SCxml.InternalEvent

SCxml.Error=function (name, src, err)
{
	SCxml.Event.call(this, name)
	this.srcElement=src||null
	this.err=err
	if(src && src.tagName=="send")
		this.sendid=src.getAttribute("id")
}
SCxml.Error.prototype=new SCxml.Event()
SCxml.Error.prototype.constructor=SCxml.Error

SCxml.ExternalEvent=function (name, origin, origintype,
	invokeid, data)
{
	SCxml.Event.call(this, name, "external")
	this.origin=origin||""
	this.origintype=origintype||""
	this.invokeid=invokeid||""
	this.data=data||{}
}
SCxml.ExternalEvent.prototype=new SCxml.Event()
SCxml.ExternalEvent.prototype.constructor=SCxml.ExternalEvent

SCxml.ExternalEvent.DOMRefCount=1
SCxml.ExternalEvent.targetOfElement=function (e)
{
	if(e instanceof Element)
		return "//*[@scxmlref=\""+(e.getAttribute("scxmlref")
		|| (e.setAttribute("scxmlref", SCxml.ExternalEvent.DOMRefCount)
			, SCxml.ExternalEvent.DOMRefCount++))+"\"]"
	return e
}

SCxml.ExternalEvent.fromDOMEvent=function (de)
{
	var e=new SCxml.ExternalEvent(de.type,
		SCxml.ExternalEvent.targetOfElement(de.srcElement), "DOM")
	e.timeStamp=de.timeStamp

	if(de instanceof CustomEvent)
		e.data=de.detail
	else for(var prop in de) if(de.hasOwnProperty(prop))
		e.data[prop]=SCxml.ExternalEvent.targetOfElement(de[prop])
	return e
}
<commit_msg>full DOM ioproc URI in converted DOM events's origintype<commit_after>/*
Constructors for SCXML events, since the browser's built-in DOM Events
are not ideally suited for that role.
*/

// the basic constructor:
SCxml.Event=function SCxmlEvent(name, type)
{
	this.name=name
	this.timestamp=new Date().getTime()
	this.type=type||"platform"
}

SCxml.Event.prototype.toString=function ()
{ return "SCxmlEvent("+this.name+")" }
SCxml.Event.prototype.match=function (t)
// matches transitions and events, e.g. "user.*" matches "user.login"
// the argument is an actual <transtion> element
{
	var patterns=t.getAttribute("event").split(/\s+/)
	var event=this.name.split(".")

	overPatterns: for(var i=0, p; p=patterns[i]; i++)
	{
		if((p=p.split(".")).length>event.length) continue
		for(var j=0; j<p.length; j++)
			if(p[j]!="*" && p[j]!=event[j]) continue overPatterns
		return true
	}
	return false
}

// sub-constructors for internal, error and external events:

SCxml.InternalEvent=function (name, src)
{
	SCxml.Event.call(this, name, "internal")
	this.srcElement=src||null
}
SCxml.InternalEvent.prototype=new SCxml.Event()
SCxml.InternalEvent.prototype.constructor=SCxml.InternalEvent

SCxml.Error=function (name, src, err)
{
	SCxml.Event.call(this, name)
	this.srcElement=src||null
	this.err=err
	if(src && src.tagName=="send")
		this.sendid=src.getAttribute("id")
}
SCxml.Error.prototype=new SCxml.Event()
SCxml.Error.prototype.constructor=SCxml.Error

SCxml.ExternalEvent=function (name, origin, origintype,
	invokeid, data)
{
	SCxml.Event.call(this, name, "external")
	this.origin=origin||""
	this.origintype=origintype||""
	this.invokeid=invokeid||""
	this.data=data||{}
}
SCxml.ExternalEvent.prototype=new SCxml.Event()
SCxml.ExternalEvent.prototype.constructor=SCxml.ExternalEvent

SCxml.ExternalEvent.DOMRefCount=1
SCxml.ExternalEvent.targetOfElement=function (e)
{
	if(e instanceof Element)
		return "//*[@scxmlref=\""+(e.getAttribute("scxmlref")
		|| (e.setAttribute("scxmlref", SCxml.ExternalEvent.DOMRefCount)
			, SCxml.ExternalEvent.DOMRefCount++))+"\"]"
	return e
}

SCxml.ExternalEvent.fromDOMEvent=function (de)
{
	var e=new SCxml.ExternalEvent(de.type,
		SCxml.ExternalEvent.targetOfElement(de.srcElement),
		SCxml.EventProcessors.DOM.name)
	e.timeStamp=de.timeStamp

	if(de instanceof CustomEvent)
		e.data=de.detail
	else for(var prop in de) if(de.hasOwnProperty(prop))
		e.data[prop]=SCxml.ExternalEvent.targetOfElement(de[prop])
	return e
}
<|endoftext|>


<commit_before>/* global BabelFileResult, BabelParserOptions, BabelFileMetadata */

import getHelper from "babel-helpers";
import convertSourceMap from "convert-source-map";
import PluginPass from "../plugin-pass";
import { NodePath, Hub, Scope } from "babel-traverse";
import sourceMap from "source-map";
import generate from "babel-generator";
import { codeFrameColumns } from "babel-code-frame";
import traverse from "babel-traverse";
import { parse } from "babylon";
import * as t from "babel-types";
import buildDebug from "debug";

import loadConfig, { type ResolvedConfig } from "../../config";

import blockHoistPlugin from "../internal-plugins/block-hoist";

const babelDebug = buildDebug("babel:file");

export function debug(opts: Object, msg: string) {
  babelDebug(`${opts.filename || "unknown"}: ${msg}`);
}

const shebangRegex = /^#!.*/;

let INTERNAL_PLUGINS;

const errorVisitor = {
  enter(path, state) {
    const loc = path.node.loc;
    if (loc) {
      state.loc = loc;
      path.stop();
    }
  },
};

export default class File {
  constructor({ options, passes }: ResolvedConfig) {
    if (!INTERNAL_PLUGINS) {
      // Lazy-init the internal plugin to remove the init-time circular dependency between plugins being
      // passed babel-core's export object, which loads this file, and this 'loadConfig' loading plugins.
      INTERNAL_PLUGINS = loadConfig({
        babelrc: false,
        plugins: [blockHoistPlugin],
      }).passes[0];
    }

    this._map = new Map();
    this.pluginPasses = passes;
    this.opts = options;

    this.parserOpts = {
      sourceType: this.opts.sourceType,
      sourceFileName: this.opts.filename,
      plugins: [],
    };

    for (const pluginPairs of passes) {
      for (const [plugin] of pluginPairs) {
        if (plugin.manipulateOptions) {
          plugin.manipulateOptions(this.opts, this.parserOpts, this);
        }
      }
    }

    this.metadata = {};
    this.declarations = {};

    this.path = null;
    this.ast = {};

    this.code = "";
    this.shebang = "";

    this.hub = new Hub(this);
  }

  static helpers: Array<string>;

  pluginPasses: Array<Array<[Plugin, Object]>>;
  parserOpts: BabelParserOptions;
  opts: Object;
  declarations: Object;
  path: NodePath;
  ast: Object;
  scope: Scope;
  metadata: BabelFileMetadata;
  hub: Hub;
  code: string;
  shebang: string;

  set(key: string, val) {
    this._map.set(key, val);
  }

  get(key: string): any {
    return this._map.get(key);
  }

  getModuleName(): ?string {
    const opts = this.opts;
    if (!opts.moduleIds) {
      return null;
    }

    // moduleId is n/a if a `getModuleId()` is provided
    if (opts.moduleId != null && !opts.getModuleId) {
      return opts.moduleId;
    }

    let filenameRelative = opts.filenameRelative;
    let moduleName = "";

    if (opts.moduleRoot != null) {
      moduleName = opts.moduleRoot + "/";
    }

    if (!opts.filenameRelative) {
      return moduleName + opts.filename.replace(/^\//, "");
    }

    if (opts.sourceRoot != null) {
      // remove sourceRoot from filename
      const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "/?");
      filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
    }

    // remove extension
    filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");

    moduleName += filenameRelative;

    // normalize path separators
    moduleName = moduleName.replace(/\\/g, "/");

    if (opts.getModuleId) {
      // If return is falsy, assume they want us to use our generated default name
      return opts.getModuleId(moduleName) || moduleName;
    } else {
      return moduleName;
    }
  }

  // TODO: Remove this before 7.x's official release. Leaving it in for now to
  // prevent unnecessary breakage between beta versions.
  resolveModuleSource(source: string): string {
    return source;
  }

  addImport() {
    throw new Error(
      "This API has been removed. If you're looking for this " +
        "functionality in Babel 7, you should import the " +
        "'babel-helper-module-imports' module and use the functions exposed " +
        " from that module, such as 'addNamed' or 'addDefault'.",
    );
  }

  addHelper(name: string): Object {
    const declar = this.declarations[name];
    if (declar) return declar;

    const generator = this.get("helperGenerator");
    const runtime = this.get("helpersNamespace");
    if (generator) {
      const res = generator(name);
      if (res) return res;
    } else if (runtime) {
      return t.memberExpression(runtime, t.identifier(name));
    }

    const ownBindingNames = Object.keys(this.scope.getAllBindings());
    const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
      name,
    ));

    const { nodes, globals } = getHelper(name, uid, ownBindingNames);

    globals.forEach(name => {
      if (this.path.scope.hasBinding(name, true /* noGlobals */)) {
        this.path.scope.rename(name);
      }
    });

    nodes.forEach(node => {
      node._compact = true;
    });

    this.path.unshiftContainer("body", nodes);

    return uid;
  }

  addTemplateObject() {
    throw new Error(
      "This function has been moved into the template literal transform itself.",
    );
  }

  buildCodeFrameError(
    node: Object,
    msg: string,
    Error: typeof Error = SyntaxError,
  ): Error {
    const loc = node && (node.loc || node._loc);

    const err = new Error(msg);

    if (loc) {
      err.loc = loc.start;
    } else {
      traverse(node, errorVisitor, this.scope, err);

      err.message +=
        " (This is an error on an internal node. Probably an internal error";

      if (err.loc) {
        err.message += ". Location has been estimated.";
      }

      err.message += ")";
    }

    return err;
  }

  mergeSourceMap(map: Object) {
    const inputMap = this.opts.inputSourceMap;

    if (inputMap) {
      const inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
      const outputMapConsumer = new sourceMap.SourceMapConsumer(map);

      const mergedGenerator = new sourceMap.SourceMapGenerator({
        file: inputMapConsumer.file,
        sourceRoot: inputMapConsumer.sourceRoot,
      });

      // This assumes the output map always has a single source, since Babel always compiles a
      // single source file to a single output file.
      const source = outputMapConsumer.sources[0];

      inputMapConsumer.eachMapping(function(mapping) {
        const generatedPosition = outputMapConsumer.generatedPositionFor({
          line: mapping.generatedLine,
          column: mapping.generatedColumn,
          source: source,
        });
        if (generatedPosition.column != null) {
          mergedGenerator.addMapping({
            source: mapping.source,

            original:
              mapping.source == null
                ? null
                : {
                    line: mapping.originalLine,
                    column: mapping.originalColumn,
                  },

            generated: generatedPosition,

            name: mapping.name,
          });
        }
      });

      const mergedMap = mergedGenerator.toJSON();
      inputMap.mappings = mergedMap.mappings;
      return inputMap;
    } else {
      return map;
    }
  }

  parse(code: string) {
    let parseCode = parse;
    let parserOpts = this.opts.parserOpts;

    if (parserOpts) {
      parserOpts = Object.assign({}, this.parserOpts, parserOpts);

      if (parserOpts.parser) {
        parseCode = parserOpts.parser;

        parserOpts.parser = {
          parse(source) {
            return parse(source, parserOpts);
          },
        };
      }
    }

    debug(this.opts, "Parse start");
    const ast = parseCode(code, parserOpts || this.parserOpts);
    debug(this.opts, "Parse stop");
    return ast;
  }

  _addAst(ast) {
    this.path = NodePath.get({
      hub: this.hub,
      parentPath: null,
      parent: ast,
      container: ast,
      key: "program",
    }).setContext();
    this.scope = this.path.scope;
    this.ast = ast;
  }

  addAst(ast) {
    debug(this.opts, "Start set AST");
    this._addAst(ast);
    debug(this.opts, "End set AST");
  }

  transform(): BabelFileResult {
    for (const pluginPairs of this.pluginPasses) {
      const passPairs = [];
      const passes = [];
      const visitors = [];

      for (const [plugin, pluginOpts] of pluginPairs.concat(INTERNAL_PLUGINS)) {
        const pass = new PluginPass(this, plugin.key, pluginOpts);

        passPairs.push([plugin, pass]);
        passes.push(pass);
        visitors.push(plugin.visitor);
      }

      for (const [plugin, pass] of passPairs) {
        const fn = plugin.pre;
        if (fn) fn.call(pass, this);
      }

      debug(this.opts, "Start transform traverse");

      // merge all plugin visitors into a single visitor
      const visitor = traverse.visitors.merge(
        visitors,
        passes,
        this.opts.wrapPluginVisitorMethod,
      );
      traverse(this.ast, visitor, this.scope);

      debug(this.opts, "End transform traverse");

      for (const [plugin, pass] of passPairs) {
        const fn = plugin.post;
        if (fn) fn.call(pass, this);
      }
    }

    return this.generate();
  }

  wrap(code: string, callback: Function): BabelFileResult {
    code = code + "";

    try {
      return callback();
    } catch (err) {
      if (err._babel) {
        throw err;
      } else {
        err._babel = true;
      }

      let message = (err.message = `${this.opts.filename}: ${err.message}`);

      const loc = err.loc;
      if (loc) {
        const location = {
          start: {
            line: loc.line,
            column: loc.column + 1,
          },
        };
        err.codeFrame = codeFrameColumns(code, location, this.opts);
        message += "\n" + err.codeFrame;
      }

      if (process.browser) {
        // chrome has it's own pretty stringifier which doesn't use the stack property
        // https://github.com/babel/babel/issues/2175
        err.message = message;
      }

      if (err.stack) {
        const newStack = err.stack.replace(err.message, message);
        err.stack = newStack;
      }

      throw err;
    }
  }

  addCode(code: string) {
    code = (code || "") + "";
    code = this.parseInputSourceMap(code);
    this.code = code;
  }

  parseCode() {
    this.parseShebang();
    const ast = this.parse(this.code);
    this.addAst(ast);
  }

  parseInputSourceMap(code: string): string {
    const opts = this.opts;

    if (opts.inputSourceMap !== false) {
      const inputMap = convertSourceMap.fromSource(code);
      if (inputMap) {
        opts.inputSourceMap = inputMap.toObject();
        code = convertSourceMap.removeComments(code);
      }
    }

    return code;
  }

  parseShebang() {
    const shebangMatch = shebangRegex.exec(this.code);
    if (shebangMatch) {
      this.shebang = shebangMatch[0];
      this.code = this.code.replace(shebangRegex, "");
    }
  }

  makeResult({ code, map, ast, ignored }: BabelFileResult): BabelFileResult {
    const result = {
      metadata: this.metadata,
      options: this.opts,
      ignored: !!ignored,
      code: null,
      ast: null,
      map: map || null,
    };

    if (this.opts.code) {
      result.code = code;
    }

    if (this.opts.ast) {
      result.ast = ast;
    }

    return result;
  }

  generate(): BabelFileResult {
    const opts = this.opts;
    const ast = this.ast;

    const result: BabelFileResult = { ast };
    if (!opts.code) return this.makeResult(result);

    let gen = generate;
    if (opts.generatorOpts && opts.generatorOpts.generator) {
      gen = opts.generatorOpts.generator;
    }

    debug(this.opts, "Generation start");

    const _result = gen(
      ast,
      opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
      this.code,
    );
    result.code = _result.code;
    result.map = _result.map;

    debug(this.opts, "Generation end");

    if (this.shebang) {
      // add back shebang
      result.code = `${this.shebang}\n${result.code}`;
    }

    if (result.map) {
      result.map = this.mergeSourceMap(result.map);
    }

    if (opts.sourceMaps === "inline" || opts.sourceMaps === "both") {
      result.code += "\n" + convertSourceMap.fromObject(result.map).toComment();
    }

    if (opts.sourceMaps === "inline") {
      result.map = null;
    }

    return this.makeResult(result);
  }
}

export { File };
<commit_msg>Remove unused helpers prop.<commit_after>/* global BabelFileResult, BabelParserOptions, BabelFileMetadata */

import getHelper from "babel-helpers";
import convertSourceMap from "convert-source-map";
import PluginPass from "../plugin-pass";
import { NodePath, Hub, Scope } from "babel-traverse";
import sourceMap from "source-map";
import generate from "babel-generator";
import { codeFrameColumns } from "babel-code-frame";
import traverse from "babel-traverse";
import { parse } from "babylon";
import * as t from "babel-types";
import buildDebug from "debug";

import loadConfig, { type ResolvedConfig } from "../../config";

import blockHoistPlugin from "../internal-plugins/block-hoist";

const babelDebug = buildDebug("babel:file");

export function debug(opts: Object, msg: string) {
  babelDebug(`${opts.filename || "unknown"}: ${msg}`);
}

const shebangRegex = /^#!.*/;

let INTERNAL_PLUGINS;

const errorVisitor = {
  enter(path, state) {
    const loc = path.node.loc;
    if (loc) {
      state.loc = loc;
      path.stop();
    }
  },
};

export default class File {
  constructor({ options, passes }: ResolvedConfig) {
    if (!INTERNAL_PLUGINS) {
      // Lazy-init the internal plugin to remove the init-time circular dependency between plugins being
      // passed babel-core's export object, which loads this file, and this 'loadConfig' loading plugins.
      INTERNAL_PLUGINS = loadConfig({
        babelrc: false,
        plugins: [blockHoistPlugin],
      }).passes[0];
    }

    this._map = new Map();
    this.pluginPasses = passes;
    this.opts = options;

    this.parserOpts = {
      sourceType: this.opts.sourceType,
      sourceFileName: this.opts.filename,
      plugins: [],
    };

    for (const pluginPairs of passes) {
      for (const [plugin] of pluginPairs) {
        if (plugin.manipulateOptions) {
          plugin.manipulateOptions(this.opts, this.parserOpts, this);
        }
      }
    }

    this.metadata = {};
    this.declarations = {};

    this.path = null;
    this.ast = {};

    this.code = "";
    this.shebang = "";

    this.hub = new Hub(this);
  }

  pluginPasses: Array<Array<[Plugin, Object]>>;
  parserOpts: BabelParserOptions;
  opts: Object;
  declarations: Object;
  path: NodePath;
  ast: Object;
  scope: Scope;
  metadata: BabelFileMetadata;
  hub: Hub;
  code: string;
  shebang: string;

  set(key: string, val) {
    this._map.set(key, val);
  }

  get(key: string): any {
    return this._map.get(key);
  }

  getModuleName(): ?string {
    const opts = this.opts;
    if (!opts.moduleIds) {
      return null;
    }

    // moduleId is n/a if a `getModuleId()` is provided
    if (opts.moduleId != null && !opts.getModuleId) {
      return opts.moduleId;
    }

    let filenameRelative = opts.filenameRelative;
    let moduleName = "";

    if (opts.moduleRoot != null) {
      moduleName = opts.moduleRoot + "/";
    }

    if (!opts.filenameRelative) {
      return moduleName + opts.filename.replace(/^\//, "");
    }

    if (opts.sourceRoot != null) {
      // remove sourceRoot from filename
      const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "/?");
      filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
    }

    // remove extension
    filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");

    moduleName += filenameRelative;

    // normalize path separators
    moduleName = moduleName.replace(/\\/g, "/");

    if (opts.getModuleId) {
      // If return is falsy, assume they want us to use our generated default name
      return opts.getModuleId(moduleName) || moduleName;
    } else {
      return moduleName;
    }
  }

  // TODO: Remove this before 7.x's official release. Leaving it in for now to
  // prevent unnecessary breakage between beta versions.
  resolveModuleSource(source: string): string {
    return source;
  }

  addImport() {
    throw new Error(
      "This API has been removed. If you're looking for this " +
        "functionality in Babel 7, you should import the " +
        "'babel-helper-module-imports' module and use the functions exposed " +
        " from that module, such as 'addNamed' or 'addDefault'.",
    );
  }

  addHelper(name: string): Object {
    const declar = this.declarations[name];
    if (declar) return declar;

    const generator = this.get("helperGenerator");
    const runtime = this.get("helpersNamespace");
    if (generator) {
      const res = generator(name);
      if (res) return res;
    } else if (runtime) {
      return t.memberExpression(runtime, t.identifier(name));
    }

    const ownBindingNames = Object.keys(this.scope.getAllBindings());
    const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
      name,
    ));

    const { nodes, globals } = getHelper(name, uid, ownBindingNames);

    globals.forEach(name => {
      if (this.path.scope.hasBinding(name, true /* noGlobals */)) {
        this.path.scope.rename(name);
      }
    });

    nodes.forEach(node => {
      node._compact = true;
    });

    this.path.unshiftContainer("body", nodes);

    return uid;
  }

  addTemplateObject() {
    throw new Error(
      "This function has been moved into the template literal transform itself.",
    );
  }

  buildCodeFrameError(
    node: Object,
    msg: string,
    Error: typeof Error = SyntaxError,
  ): Error {
    const loc = node && (node.loc || node._loc);

    const err = new Error(msg);

    if (loc) {
      err.loc = loc.start;
    } else {
      traverse(node, errorVisitor, this.scope, err);

      err.message +=
        " (This is an error on an internal node. Probably an internal error";

      if (err.loc) {
        err.message += ". Location has been estimated.";
      }

      err.message += ")";
    }

    return err;
  }

  mergeSourceMap(map: Object) {
    const inputMap = this.opts.inputSourceMap;

    if (inputMap) {
      const inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
      const outputMapConsumer = new sourceMap.SourceMapConsumer(map);

      const mergedGenerator = new sourceMap.SourceMapGenerator({
        file: inputMapConsumer.file,
        sourceRoot: inputMapConsumer.sourceRoot,
      });

      // This assumes the output map always has a single source, since Babel always compiles a
      // single source file to a single output file.
      const source = outputMapConsumer.sources[0];

      inputMapConsumer.eachMapping(function(mapping) {
        const generatedPosition = outputMapConsumer.generatedPositionFor({
          line: mapping.generatedLine,
          column: mapping.generatedColumn,
          source: source,
        });
        if (generatedPosition.column != null) {
          mergedGenerator.addMapping({
            source: mapping.source,

            original:
              mapping.source == null
                ? null
                : {
                    line: mapping.originalLine,
                    column: mapping.originalColumn,
                  },

            generated: generatedPosition,

            name: mapping.name,
          });
        }
      });

      const mergedMap = mergedGenerator.toJSON();
      inputMap.mappings = mergedMap.mappings;
      return inputMap;
    } else {
      return map;
    }
  }

  parse(code: string) {
    let parseCode = parse;
    let parserOpts = this.opts.parserOpts;

    if (parserOpts) {
      parserOpts = Object.assign({}, this.parserOpts, parserOpts);

      if (parserOpts.parser) {
        parseCode = parserOpts.parser;

        parserOpts.parser = {
          parse(source) {
            return parse(source, parserOpts);
          },
        };
      }
    }

    debug(this.opts, "Parse start");
    const ast = parseCode(code, parserOpts || this.parserOpts);
    debug(this.opts, "Parse stop");
    return ast;
  }

  _addAst(ast) {
    this.path = NodePath.get({
      hub: this.hub,
      parentPath: null,
      parent: ast,
      container: ast,
      key: "program",
    }).setContext();
    this.scope = this.path.scope;
    this.ast = ast;
  }

  addAst(ast) {
    debug(this.opts, "Start set AST");
    this._addAst(ast);
    debug(this.opts, "End set AST");
  }

  transform(): BabelFileResult {
    for (const pluginPairs of this.pluginPasses) {
      const passPairs = [];
      const passes = [];
      const visitors = [];

      for (const [plugin, pluginOpts] of pluginPairs.concat(INTERNAL_PLUGINS)) {
        const pass = new PluginPass(this, plugin.key, pluginOpts);

        passPairs.push([plugin, pass]);
        passes.push(pass);
        visitors.push(plugin.visitor);
      }

      for (const [plugin, pass] of passPairs) {
        const fn = plugin.pre;
        if (fn) fn.call(pass, this);
      }

      debug(this.opts, "Start transform traverse");

      // merge all plugin visitors into a single visitor
      const visitor = traverse.visitors.merge(
        visitors,
        passes,
        this.opts.wrapPluginVisitorMethod,
      );
      traverse(this.ast, visitor, this.scope);

      debug(this.opts, "End transform traverse");

      for (const [plugin, pass] of passPairs) {
        const fn = plugin.post;
        if (fn) fn.call(pass, this);
      }
    }

    return this.generate();
  }

  wrap(code: string, callback: Function): BabelFileResult {
    code = code + "";

    try {
      return callback();
    } catch (err) {
      if (err._babel) {
        throw err;
      } else {
        err._babel = true;
      }

      let message = (err.message = `${this.opts.filename}: ${err.message}`);

      const loc = err.loc;
      if (loc) {
        const location = {
          start: {
            line: loc.line,
            column: loc.column + 1,
          },
        };
        err.codeFrame = codeFrameColumns(code, location, this.opts);
        message += "\n" + err.codeFrame;
      }

      if (process.browser) {
        // chrome has it's own pretty stringifier which doesn't use the stack property
        // https://github.com/babel/babel/issues/2175
        err.message = message;
      }

      if (err.stack) {
        const newStack = err.stack.replace(err.message, message);
        err.stack = newStack;
      }

      throw err;
    }
  }

  addCode(code: string) {
    code = (code || "") + "";
    code = this.parseInputSourceMap(code);
    this.code = code;
  }

  parseCode() {
    this.parseShebang();
    const ast = this.parse(this.code);
    this.addAst(ast);
  }

  parseInputSourceMap(code: string): string {
    const opts = this.opts;

    if (opts.inputSourceMap !== false) {
      const inputMap = convertSourceMap.fromSource(code);
      if (inputMap) {
        opts.inputSourceMap = inputMap.toObject();
        code = convertSourceMap.removeComments(code);
      }
    }

    return code;
  }

  parseShebang() {
    const shebangMatch = shebangRegex.exec(this.code);
    if (shebangMatch) {
      this.shebang = shebangMatch[0];
      this.code = this.code.replace(shebangRegex, "");
    }
  }

  makeResult({ code, map, ast, ignored }: BabelFileResult): BabelFileResult {
    const result = {
      metadata: this.metadata,
      options: this.opts,
      ignored: !!ignored,
      code: null,
      ast: null,
      map: map || null,
    };

    if (this.opts.code) {
      result.code = code;
    }

    if (this.opts.ast) {
      result.ast = ast;
    }

    return result;
  }

  generate(): BabelFileResult {
    const opts = this.opts;
    const ast = this.ast;

    const result: BabelFileResult = { ast };
    if (!opts.code) return this.makeResult(result);

    let gen = generate;
    if (opts.generatorOpts && opts.generatorOpts.generator) {
      gen = opts.generatorOpts.generator;
    }

    debug(this.opts, "Generation start");

    const _result = gen(
      ast,
      opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
      this.code,
    );
    result.code = _result.code;
    result.map = _result.map;

    debug(this.opts, "Generation end");

    if (this.shebang) {
      // add back shebang
      result.code = `${this.shebang}\n${result.code}`;
    }

    if (result.map) {
      result.map = this.mergeSourceMap(result.map);
    }

    if (opts.sourceMaps === "inline" || opts.sourceMaps === "both") {
      result.code += "\n" + convertSourceMap.fromObject(result.map).toComment();
    }

    if (opts.sourceMaps === "inline") {
      result.map = null;
    }

    return this.makeResult(result);
  }
}

export { File };
<|endoftext|>


<commit_before>/**
 * Before unload message
 */
(function($) {
    $(function() {
        $(window).on('beforeunload', function() {
            return '$message';
        });
    });
})(jQuery);<commit_msg>don't be overzealous<commit_after>/**
 * Before unload message
 */
(function($) {
    $(function() {
        $(window).on('beforeunload', function() {
            return '$message';
        });
        $('form').on('submit', function() {
            $(window).off('beforeunload');
        });
    });
})(jQuery);<|endoftext|>


<commit_before>(function (win) {

    if (!(win.history && win.history.pushState))
        return;

    var submitData = {};
    win.document.addEventListener('click', function (e) {
        var element = e.target;
        var anchor = getAjaxTarget(element, 'A');
        if (!e.ctrlKey && !e.shiftKey && anchor) {
            e.preventDefault();
            refreshAjax(anchor.getAttribute('href'), true, anchor);
        }
        if (element.tagName === 'INPUT' && element.name) {
            if (element.type === 'submit')
                submitData[element.name] = element.value;
            if (element.type === 'image') {
                submitData[element.name + '.x'] = win.Math.max(0, e.offsetX);
                submitData[element.name + '.y'] = win.Math.max(0, e.offsetY);
            }
        }
    });

    win.document.addEventListener('submit', function (e) {
        var form = getAjaxTarget(e.target, 'FORM');
        if (form) {
            var req = new win.XMLHttpRequest();
            req.onreadystatechange = onReady(req, true);
            e.preventDefault();
            req.open('post', getAjaxLink(form.getAttribute('action'), form));
            req.setRequestHeader("Content-Type", "application/json");
            req.send(win.JSON.stringify(getFormData(form)));
        }
    });

    var tagNames = /^INPUT|TEXTAREA|SELECT$/;
    var ignoreTypes = /^button|image|submit|reset|file$/;
    var checkTypes = /^checkbox|radio$/;
    function getFormData(form) {
        var elements = form.elements;
        var data = {};
        for (var i = 0; i < elements.length; i++) {
            var element = elements[i];
            if (tagNames.test(element.tagName) && element.name
                && !ignoreTypes.test(element.type) && !element.disabled
                && (!checkTypes.test(element.type) || element.checked))
                data[element.name] = element.value;
        }
        for (var key in submitData)
            data[key] = submitData[key];
        submitData = {};
        return data;
    }

    function getAjaxTarget(element, tagName) {
        var target = null;
        while (element) {
            if (element.getAttribute) {
                var navigation = element.getAttribute('data-navigation');
                if (!target && element.tagName === tagName && navigation === 'refresh')
                    target = element;
                if (navigation === 'noajax')
                    return null;
            }
            element = element.parentNode;
        }
        return target;
    }

    var link = win.location.pathname + win.location.search;
    function refreshAjax(newLink, addHistory, target, title) {
        var req = new win.XMLHttpRequest();
        req.onreadystatechange = onReady(req, addHistory, title);
        req.open('get', getAjaxLink(newLink, target));
        req.send();
    }

    function getAjaxLink(baseLink, target) {
        baseLink += baseLink.indexOf('?') > 0 ? '&' : '?';
        baseLink += 'refreshajax=' + win.encodeURIComponent(link);
        baseLink += '&navigation=' + (target ? 'refresh' : 'history');
        if (target) {
            baseLink = setLinkData(target, baseLink, 'include-current');
            baseLink = setLinkData(target, baseLink, 'current-keys');
            baseLink = setLinkData(target, baseLink, 'to-keys');
        }
        return baseLink;
    }

    function setLinkData(target, link, name) {
        var value = target.getAttribute('data-' + name);
        if (value)
            link += '&' + name.replace('-','') + '=' + win.encodeURIComponent(value);
        return link;
    }

    var cache = {};
    function onReady(req, addHistory, title) {
        var oldLink = link;
        return function () {
            if (req.readyState === 4 && req.status === 200) {
                var resp = win.JSON.parse(req.responseText);
                if (!resp.Title)
                    resp.Title = title ? title : win.document.title;
                handleRespone(resp, addHistory, oldLink);
            }
        };
    }

    function handleRespone(resp, addHistory, oldLink) {
        if (resp.RedirectLink) {
            win.location.href = resp.RedirectLink;
            return;
        }
        var newLink = resp.Link;
        cache[oldLink + '&' + newLink] = resp;
        if (link !== oldLink)
            return;
        for (var id in resp.Panels) {
            var panel = win.document.getElementById(id);
            panel.innerHTML = resp.Panels[id];
            var evt;
            if (typeof win.Event === 'function')
                evt = new win.Event('refreshajax');
            else {
                evt = win.document.createEvent('Event');
                evt.initEvent('refreshajax', false, false);
            }
            panel.dispatchEvent(evt);
        }
        if (addHistory && link !== newLink)
            win.history.pushState(resp.Title, resp.Title, newLink);
        win.document.title = resp.Title;
        link = newLink;
    }

    win.addEventListener('popstate', function (e) {
        var newLink = win.location.pathname + win.location.search;
        if (link !== newLink) {
            var resp = cache[link + '&' + newLink];
            if (!resp)
                refreshAjax(newLink, false, null, e.state);
            else {
                try {
                    handleRespone(resp, false, link);
                } catch (ex) {
                    refreshAjax(newLink, false, null, e.state);
                }
            }
        }
    });
})(window);<commit_msg>Make a back response on the client. A -> B means cache AB(resp from server) and BA (resp made on client) So pressing back won't go to the server because BA is cached.<commit_after>(function (win) {

    if (!(win.history && win.history.pushState))
        return;

    var submitData = {};
    win.document.addEventListener('click', function (e) {
        var element = e.target;
        var anchor = getAjaxTarget(element, 'A');
        if (!e.ctrlKey && !e.shiftKey && anchor) {
            e.preventDefault();
            refreshAjax(anchor.getAttribute('href'), true, anchor);
        }
        if (element.tagName === 'INPUT' && element.name) {
            if (element.type === 'submit')
                submitData[element.name] = element.value;
            if (element.type === 'image') {
                submitData[element.name + '.x'] = win.Math.max(0, e.offsetX);
                submitData[element.name + '.y'] = win.Math.max(0, e.offsetY);
            }
        }
    });

    win.document.addEventListener('submit', function (e) {
        var form = getAjaxTarget(e.target, 'FORM');
        if (form) {
            var req = new win.XMLHttpRequest();
            req.onreadystatechange = onReady(req, true);
            e.preventDefault();
            req.open('post', getAjaxLink(form.getAttribute('action'), form));
            req.setRequestHeader("Content-Type", "application/json");
            req.send(win.JSON.stringify(getFormData(form)));
        }
    });

    var tagNames = /^INPUT|TEXTAREA|SELECT$/;
    var ignoreTypes = /^button|image|submit|reset|file$/;
    var checkTypes = /^checkbox|radio$/;
    function getFormData(form) {
        var elements = form.elements;
        var data = {};
        for (var i = 0; i < elements.length; i++) {
            var element = elements[i];
            if (tagNames.test(element.tagName) && element.name
                && !ignoreTypes.test(element.type) && !element.disabled
                && (!checkTypes.test(element.type) || element.checked))
                data[element.name] = element.value;
        }
        for (var key in submitData)
            data[key] = submitData[key];
        submitData = {};
        return data;
    }

    function getAjaxTarget(element, tagName) {
        var target = null;
        while (element) {
            if (element.getAttribute) {
                var navigation = element.getAttribute('data-navigation');
                if (!target && element.tagName === tagName && navigation === 'refresh')
                    target = element;
                if (navigation === 'noajax')
                    return null;
            }
            element = element.parentNode;
        }
        return target;
    }

    var link = win.location.pathname + win.location.search;
    function refreshAjax(newLink, addHistory, target, title) {
        var req = new win.XMLHttpRequest();
        req.onreadystatechange = onReady(req, addHistory, title);
        req.open('get', getAjaxLink(newLink, target));
        req.send();
    }

    function getAjaxLink(baseLink, target) {
        baseLink += baseLink.indexOf('?') > 0 ? '&' : '?';
        baseLink += 'refreshajax=' + win.encodeURIComponent(link);
        baseLink += '&navigation=' + (target ? 'refresh' : 'history');
        if (target) {
            baseLink = setLinkData(target, baseLink, 'include-current');
            baseLink = setLinkData(target, baseLink, 'current-keys');
            baseLink = setLinkData(target, baseLink, 'to-keys');
        }
        return baseLink;
    }

    function setLinkData(target, link, name) {
        var value = target.getAttribute('data-' + name);
        if (value)
            link += '&' + name.replace('-','') + '=' + win.encodeURIComponent(value);
        return link;
    }

    var cache = {};
    function onReady(req, addHistory, title) {
        var oldLink = link;
        return function () {
            if (req.readyState === 4 && req.status === 200) {
                var resp = win.JSON.parse(req.responseText);
                if (!resp.Title)
                    resp.Title = title ? title : win.document.title;
                handleRespone(resp, addHistory, oldLink);
            }
        };
    }

    function handleRespone(resp, addHistory, oldLink) {
        if (resp.RedirectLink) {
            win.location.href = resp.RedirectLink;
            return;
        }
        var newLink = resp.Link;
        cache[oldLink + '&' + newLink] = resp;
        if (link !== oldLink)
            return;
        var backResp = {};
        backResp.Link = link;
        backResp.Title = win.document.title;
        backResp.Panels = {};
        for (var id in resp.Panels) {
            var panel = win.document.getElementById(id);
            backResp.Panels[id] = panel.innerHTML;
            panel.innerHTML = resp.Panels[id];
            var evt;
            if (typeof win.Event === 'function')
                evt = new win.Event('refreshajax');
            else {
                evt = win.document.createEvent('Event');
                evt.initEvent('refreshajax', false, false);
            }
            panel.dispatchEvent(evt);
        }
        cache[newLink + '&' + link] = backResp;
        if (addHistory && link !== newLink)
            win.history.pushState(resp.Title, resp.Title, newLink);
        win.document.title = resp.Title;
        link = newLink;
    }

    win.addEventListener('popstate', function (e) {
        var newLink = win.location.pathname + win.location.search;
        if (link !== newLink) {
            var resp = cache[link + '&' + newLink];
            if (!resp)
                refreshAjax(newLink, false, null, e.state);
            else {
                try {
                    handleRespone(resp, false, link);
                } catch (ex) {
                    refreshAjax(newLink, false, null, e.state);
                }
            }
        }
    });
})(window);<|endoftext|>