<commit_before>// util.js v3.4.0

//----------------------------------------------------------------------
// EventやDOM関連のツール的関数群
//----------------------------------------------------------------------
pzpr.util = {
	//---------------------------------------------------------------
	// pzpr.jsが読み込まれているスクリプトのパスを取得する
	getpath : function(filename){
		filename = filename || "pzprv3.js";
		var srcs=document.getElementsByTagName('script');
		for(var i=0;i<srcs.length;i++){
			var result = srcs[i].src.match(new RegExp("^(.*\\/)"+filename+"$"));
			if(result){ return result[1] + (!result[1].match(/\/$/) ? '/' : '');}
		}
		return "";
	},

	//---------------------------------------------------------------
	// 現在の時間を取得
	currentTime : function(){ return (new Date()).getTime();},

	//---------------------------------------------------------------
	// 言語環境をチェックして日本語かどうか判定する
	getUserLang : function(){
		var userlang = (navigator.browserLanguage || navigator.language || navigator.userLanguage);
		return ((userlang.substr(0,2)==='ja')?'ja':'en');
	},

	//---------------------------------------------------------------
	// Elementの生成関連
	//---------------------------------------------------------------
	unselectable : function(el){
		el.style.MozUserSelect    = 'none';
		el.style.KhtmlUserSelect  = 'none';
		el.style.webkitUserSelect = 'none';
		el.style.msUserSelect     = 'none';
		el.style.userSelect       = 'none';
		el.unselectable = "on";
		return this;
	},

	//----------------------------------------------------------------------
	// pzpr.util.addEvent()          addEventListener(など)を呼び出す
	// pzpr.util.addMouseDownEvent() マウスを押したときのイベントを設定する
	// pzpr.util.addMouseMoveEvent() マウスを動かしたときのイベントを設定する
	// pzpr.util.addMouseUpEvent()   マウスボタンを離したときのイベントを設定する
	//----------------------------------------------------------------------
	addEvent : function(el, event, self, callback, capt){
		var func = function(e){
			e = e || window.event;
			if(!e.target){ e.target = e.srcElement;}
			callback.call(self, e);
		};
		if(!!el.addEventListener){ el.addEventListener(event, func, !!capt);}
		else                     { el.attachEvent('on'+event, func);}
	},
	addMouseDownEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointerdown", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerDown", self, func);
		}
		else{
			this.addEvent(el, "mousedown", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchstart", self, func);
			}
		}
	},
	addMouseMoveEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointermove", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerMove", self, func);
		}
		else{
			this.addEvent(el, "mousemove", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchmove",  self, func);
			}
		}
	},
	addMouseUpEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointerup", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerUp", self, func);
		}
		else{
			this.addEvent(el, "mouseup", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchend", self, func);
			}
		}
	},

	//---------------------------------------------------------------------------
	// pzpr.util.getMouseButton() 左/中/右ボタンが押されているかチェックする
	//---------------------------------------------------------------------------
	getMouseButton : function(e){
		var left=false, mid=false, right=false;
		if(e.touches!==void 0){
			/* touchイベントだった場合 */
			left  = (e.touches.length===1);
			right = (e.touches.length>1);
		}
		else{
			if(!pzpr.env.browser.IE8){
				left  = (!!e.which ? e.which===1 : e.button===0);
				mid   = (!!e.which ? e.which===2 : e.button===1);
				right = (!!e.which ? e.which===3 : e.button===2);
			}
			else{
				left  = (e.button===1);
				mid   = (e.button===4);
				right = (e.button===2);
			}
		}

		return {Left:left, Middle:mid, Right:right};
	},

	//----------------------------------------------------------------------
	// pzpr.util.getPagePos() イベントが起こったページ上の座標を返す
	// pzpr.util.pageX()      イベントが起こったページ上のX座標を返す
	// pzpr.util.pageY()      イベントが起こったページ上のY座標を返す
	//----------------------------------------------------------------------
	getPagePos : function(e){
		return {px:this.pageX(e), py:this.pageY(e)};
	},
	pageX : function(e){
		function scrollLeft(){ return (document.documentElement.scrollLeft || document.body.scrollLeft);}
		if(e.touches!==void 0 && e.touches.length>0){
			var len=e.touches.length, pos=0;
			if(len>0){
				for(var i=0;i<len;i++){ pos += e.touches[i].pageX;}
				return pos/len;
			}
		}
		else if(!isNaN(e.pageX)){ return e.pageX;}
		else if(!isNaN(e.clientX)){ return e.clientX + scrollLeft();}
		return 0;
	},
	pageY : function(e){
		function scrollTop(){ return (document.documentElement.scrollTop  || document.body.scrollTop );}
		if(e.touches!==void 0 && e.touches.length>0){
			var len=e.touches.length, pos=0;
			if(len>0){
				for(var i=0;i<len;i++){ pos += e.touches[i].pageY;}
				return pos/len;
			}
		}
		else if(!isNaN(e.pageY)){ return e.pageY;}
		else if(!isNaN(e.clientY)){ return e.clientY + scrollTop();}
		return 0;
	},

	//--------------------------------------------------------------------------------
	// pzpr.util.getRect()   エレメントの四辺の座標を返す
	//--------------------------------------------------------------------------------
	getRect : function(el){
		this.getRect = ((!!document.createElement('div').getBoundingClientRect) ?
			function(el){
				var rect = el.getBoundingClientRect(), _html, _body, scrollLeft, scrollTop;
				if(window.scrollX!==void 0){
					scrollLeft = window.scrollX;
					scrollTop  = window.scrollY;
				}
				else{
					_html = document.documentElement; _body = document.body;
					scrollLeft = (_body.scrollLeft || _html.scrollLeft) - _html.clientLeft;
					scrollTop  = (_body.scrollTop  || _html.scrollTop ) - _html.clientTop;
				}
				var left   = rect.left   + scrollLeft;
				var top    = rect.top    + scrollTop;
				var right  = rect.right  + scrollLeft;
				var bottom = rect.bottom + scrollTop;
				return { top:top, bottom:bottom, left:left, right:right};
			}
		:
			function(el){
				var left = 0, top = 0, el2 = el;
				while(!!el2){
					left += +(!isNaN(el2.offsetLeft) ? el2.offsetLeft : el2.clientLeft);
					top  += +(!isNaN(el2.offsetTop)  ? el2.offsetTop  : el2.clientTop );
					el2 = el2.offsetParent;
				}
				var right  = left + (el.offsetWidth  || el.clientWidth);
				var bottom = top  + (el.offsetHeight || el.clientHeight);
				return { top:top, bottom:bottom, left:left, right:right};
			}
		);
		return this.getRect(el);
	},

	//----------------------------------------------------------------------
	// Eventオブジェクト関連
	//
	// stopPropagation() イベントの起こったエレメントより上にイベントを
	//                   伝播させないようにする
	// preventDefault()  イベントの起こったエレメントで、デフォルトの
	//                   イベントが起こらないようにする
	//----------------------------------------------------------------------
	stopPropagation : function(e){
		if(!!e.stopPropagation){ e.stopPropagation();}
		else{ e.cancelBubble = true;}
	},
	preventDefault : function(e){
		if(!!e.preventDefault){ e.preventDefault();}
		else{ e.returnValue = false;}
	}
};
<commit_msg>pzpr.util: 不要な互換性確保コードを削除します<commit_after>// util.js v3.4.0

//----------------------------------------------------------------------
// EventやDOM関連のツール的関数群
//----------------------------------------------------------------------
pzpr.util = {
	//---------------------------------------------------------------
	// pzpr.jsが読み込まれているスクリプトのパスを取得する
	getpath : function(filename){
		filename = filename || "pzprv3.js";
		var srcs=document.getElementsByTagName('script');
		for(var i=0;i<srcs.length;i++){
			var result = srcs[i].src.match(new RegExp("^(.*\\/)"+filename+"$"));
			if(result){ return result[1] + (!result[1].match(/\/$/) ? '/' : '');}
		}
		return "";
	},

	//---------------------------------------------------------------
	// 現在の時間を取得
	currentTime : function(){ return (new Date()).getTime();},

	//---------------------------------------------------------------
	// 言語環境をチェックして日本語かどうか判定する
	getUserLang : function(){
		var userlang = (navigator.browserLanguage || navigator.language || navigator.userLanguage);
		return ((userlang.substr(0,2)==='ja')?'ja':'en');
	},

	//---------------------------------------------------------------
	// Elementの生成関連
	//---------------------------------------------------------------
	unselectable : function(el){
		el.style.MozUserSelect    = 'none';
		el.style.KhtmlUserSelect  = 'none';
		el.style.webkitUserSelect = 'none';
		el.style.msUserSelect     = 'none';
		el.style.userSelect       = 'none';
		el.unselectable = "on";
		return this;
	},

	//----------------------------------------------------------------------
	// pzpr.util.addEvent()          addEventListener(など)を呼び出す
	// pzpr.util.addMouseDownEvent() マウスを押したときのイベントを設定する
	// pzpr.util.addMouseMoveEvent() マウスを動かしたときのイベントを設定する
	// pzpr.util.addMouseUpEvent()   マウスボタンを離したときのイベントを設定する
	//----------------------------------------------------------------------
	addEvent : function(el, event, self, callback, capt){
		var func = function(e){
			e = e || window.event;
			if(!e.target){ e.target = e.srcElement;}
			callback.call(self, e);
		};
		if(!!el.addEventListener){ el.addEventListener(event, func, !!capt);}
		else                     { el.attachEvent('on'+event, func);}
	},
	addMouseDownEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointerdown", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerDown", self, func);
		}
		else{
			this.addEvent(el, "mousedown", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchstart", self, func);
			}
		}
	},
	addMouseMoveEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointermove", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerMove", self, func);
		}
		else{
			this.addEvent(el, "mousemove", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchmove",  self, func);
			}
		}
	},
	addMouseUpEvent : function(el, self, func){
		if(pzpr.env.API.pointerevent){
			this.addEvent(el, "pointerup", self, func);
		}
		else if(pzpr.env.API.mspointerevent){
			this.addEvent(el, "MSPointerUp", self, func);
		}
		else{
			this.addEvent(el, "mouseup", self, func);
			if(pzpr.env.API.touchevent){
				this.addEvent(el, "touchend", self, func);
			}
		}
	},

	//---------------------------------------------------------------------------
	// pzpr.util.getMouseButton() 左/中/右ボタンが押されているかチェックする
	//---------------------------------------------------------------------------
	getMouseButton : function(e){
		var left=false, mid=false, right=false;
		if(e.touches!==void 0){
			/* touchイベントだった場合 */
			left  = (e.touches.length===1);
			right = (e.touches.length>1);
		}
		else if(!pzpr.env.browser.IE8){
			left  = (!!e.which ? e.which===1 : e.button===0);
			mid   = (!!e.which ? e.which===2 : e.button===1);
			right = (!!e.which ? e.which===3 : e.button===2);
		}
		else{
			left  = (e.button===1);
			mid   = (e.button===4);
			right = (e.button===2);
		}

		return {Left:left, Middle:mid, Right:right};
	},

	//----------------------------------------------------------------------
	// pzpr.util.getPagePos() イベントが起こったページ上の座標を返す
	// pzpr.util.pageX()      イベントが起こったページ上のX座標を返す
	// pzpr.util.pageY()      イベントが起こったページ上のY座標を返す
	//----------------------------------------------------------------------
	getPagePos : function(e){
		return {px:this.pageX(e), py:this.pageY(e)};
	},
	pageX : function(e){
		if(e.touches!==void 0 && e.touches.length>0){
			var len=e.touches.length, pos=0;
			if(len>0){
				for(var i=0;i<len;i++){ pos += e.touches[i].pageX;}
				return pos/len;
			}
		}
		else if(!isNaN(e.pageX)){ return e.pageX;}
		else if(!isNaN(e.clientX)){ return e.clientX + document.documentElement.scrollLeft;} /* IE8以下向け */
		return 0;
	},
	pageY : function(e){
		if(e.touches!==void 0 && e.touches.length>0){
			var len=e.touches.length, pos=0;
			if(len>0){
				for(var i=0;i<len;i++){ pos += e.touches[i].pageY;}
				return pos/len;
			}
		}
		else if(!isNaN(e.pageY)){ return e.pageY;}
		else if(!isNaN(e.clientY)){ return e.clientY + document.documentElement.scrollTop;} /* IE8以下向け */
		return 0;
	},

	//--------------------------------------------------------------------------------
	// pzpr.util.getRect()   エレメントの四辺の座標を返す
	//--------------------------------------------------------------------------------
	getRect : function(el){
		var rect = el.getBoundingClientRect(), _html, _body, scrollLeft, scrollTop;
		if(window.scrollX!==void 0){
			scrollLeft = window.scrollX;
			scrollTop  = window.scrollY;
		}
		else{
			/* IE8以下向け */
			_html = document.documentElement; _body = document.body;
			scrollLeft = _body.scrollLeft - _html.clientLeft;
			scrollTop  = _body.scrollTop  - _html.clientTop;
		}
		var left   = rect.left   + scrollLeft;
		var top    = rect.top    + scrollTop;
		var right  = rect.right  + scrollLeft;
		var bottom = rect.bottom + scrollTop;
		return { top:top, bottom:bottom, left:left, right:right};
	},

	//----------------------------------------------------------------------
	// Eventオブジェクト関連
	//
	// stopPropagation() イベントの起こったエレメントより上にイベントを
	//                   伝播させないようにする
	// preventDefault()  イベントの起こったエレメントで、デフォルトの
	//                   イベントが起こらないようにする
	//----------------------------------------------------------------------
	stopPropagation : function(e){
		if(!!e.stopPropagation){ e.stopPropagation();}
		else{ e.cancelBubble = true;}
	},
	preventDefault : function(e){
		if(!!e.preventDefault){ e.preventDefault();}
		else{ e.returnValue = false;}
	}
};
<|endoftext|>


<commit_before>// Create the clobal audio co ntext
context = new (window.AudioContext || window.webkitAudioContext)();

// Some cross-platform bulletproofing
if (!context.createGain) {
  context.createGain = context.createGainNode;
}
if (!context.createDelay)
  context.createDelay = context.createDelayNode;
if (!context.createScriptProcessor)
  context.createScriptProcessor = context.createJavaScriptNode;

// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return  window.requestAnimationFrame       ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame    ||
  window.oRequestAnimationFrame      ||
  window.msRequestAnimationFrame     ||
  function( callback ){
  window.setTimeout(callback, 1000 / 60);
};
})();
// end cross-platform bulletproofing

var stn1 = new Station("F5IN", context.destination);
var stn2 = new Station("W6YX", context.destination);
var noise = new NoiseSource(context.destination);

setPitch = function(newPitch, station) {
  if (!isNaN(newPitch)) {
    station.keyer.setPitch(newPitch);
  }
}

setSpeed = function(newSpeed, station) {
  if (!isNaN(newSpeed)) {
    station.keyer.setSpeed(newSpeed);
  }
}

setGain = function(newGain, station) {
  if (!isNaN(newGain)) {
    newGain = newGain / 100.0;
    station.keyer.setMonitorGain(newGain);
  }
}

setNoiseGain = function(newGain) {
  if (!isNaN(newGain)) {
    newGain = newGain / 100.0;
    noise.setGain(newGain);
  }
}

$( document ).ready(function() {
  console.log("READY");
  setPitch($('#pitch1').val(), stn1);
  setSpeed($('#speed1').val(), stn1);
  setGain($('#gain1').val(), stn1);

  setPitch($('#pitch2').val(), stn2);
  setSpeed($('#speed2').val(), stn2);
  setGain($('#gain2').val(), stn2);

  setNoiseGain($('#noise_gain').val());
});

$(function() {

  $("#send1").click(function() {
    if (stn1.keyer.isSending()) {
        console.log("Can't send now, keyer 1 sending");
    } else {
        stn1.keyer.send(document.getElementById("send_text1").value);
    }
  });

  $("#send2").click(function() {
    console.log("click 2");
    if (stn2.keyer.isSending()) {
        console.log("Can't send now, keyer 2 sending");
    } else {
        stn2.keyer.send(document.getElementById("send_text2").value);
    }
  });

  $("#cancel1").click(function() {
    stn1.keyer.abortMessage();
  });

  $("#cancel2").click(function() {
    stn2.keyer.abortMessage();
  });

  $("#pitch1").on('input', function() {
    newPitch = $('#pitch1').val();
    setPitch(newPitch, stn1);
  });

  $("#pitch2").on('input', function() {
    newPitch = $('#pitch2').val();
    setPitch(newPitch, stn2);
  });

  $("#speed1").on('input', function() {
    newSpeed = $('#speed1').val();
    setSpeed(newSpeed, stn1);
  });

  $("#speed2").on('input', function() {
    newSpeed = $('#speed2').val();
    setSpeed(newSpeed, stn2);
  });

  $("#gain1").on('input', function() {
    newgain = $('#gain1').val();
    if (newGain > 100) {
      newGain = 100;
      $("#gain1").val(newGain);
    }
    setGain(newgain, stn1);
  });

  $("#gain2").on('input', function() {
    newGain = $('#gain2').val();
    if (newGain > 100) {
      newGain = 100;
      $("#gain2").val(newGain);
    }
    setGain(newGain, stn2);
  });

  $("#noise").change(function() {
    noise.setEnabled(this.checked);
  });

  $("#noise_gain").on('input', function() {
    newGain = $('#noise_gain').val();
    if (newGain > 100) {
      newGain = 100;
      $("#noise_gain").val(newGain);
    }
    setNoiseGain(newGain);
  });
});
<commit_msg>Fix typo in var name<commit_after>// Create the clobal audio co ntext
context = new (window.AudioContext || window.webkitAudioContext)();

// Some cross-platform bulletproofing
if (!context.createGain) {
  context.createGain = context.createGainNode;
}
if (!context.createDelay)
  context.createDelay = context.createDelayNode;
if (!context.createScriptProcessor)
  context.createScriptProcessor = context.createJavaScriptNode;

// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return  window.requestAnimationFrame       ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame    ||
  window.oRequestAnimationFrame      ||
  window.msRequestAnimationFrame     ||
  function( callback ){
  window.setTimeout(callback, 1000 / 60);
};
})();
// end cross-platform bulletproofing

var stn1 = new Station("F5IN", context.destination);
var stn2 = new Station("W6YX", context.destination);
var noise = new NoiseSource(context.destination);

setPitch = function(newPitch, station) {
  if (!isNaN(newPitch)) {
    station.keyer.setPitch(newPitch);
  }
}

setSpeed = function(newSpeed, station) {
  if (!isNaN(newSpeed)) {
    station.keyer.setSpeed(newSpeed);
  }
}

setGain = function(newGain, station) {
  if (!isNaN(newGain)) {
    newGain = newGain / 100.0;
    station.keyer.setMonitorGain(newGain);
  }
}

setNoiseGain = function(newGain) {
  if (!isNaN(newGain)) {
    newGain = newGain / 100.0;
    noise.setGain(newGain);
  }
}

$( document ).ready(function() {
  console.log("READY");
  setPitch($('#pitch1').val(), stn1);
  setSpeed($('#speed1').val(), stn1);
  setGain($('#gain1').val(), stn1);

  setPitch($('#pitch2').val(), stn2);
  setSpeed($('#speed2').val(), stn2);
  setGain($('#gain2').val(), stn2);

  setNoiseGain($('#noise_gain').val());
});

$(function() {

  $("#send1").click(function() {
    if (stn1.keyer.isSending()) {
        console.log("Can't send now, keyer 1 sending");
    } else {
        stn1.keyer.send(document.getElementById("send_text1").value);
    }
  });

  $("#send2").click(function() {
    console.log("click 2");
    if (stn2.keyer.isSending()) {
        console.log("Can't send now, keyer 2 sending");
    } else {
        stn2.keyer.send(document.getElementById("send_text2").value);
    }
  });

  $("#cancel1").click(function() {
    stn1.keyer.abortMessage();
  });

  $("#cancel2").click(function() {
    stn2.keyer.abortMessage();
  });

  $("#pitch1").on('input', function() {
    newPitch = $('#pitch1').val();
    setPitch(newPitch, stn1);
  });

  $("#pitch2").on('input', function() {
    newPitch = $('#pitch2').val();
    setPitch(newPitch, stn2);
  });

  $("#speed1").on('input', function() {
    newSpeed = $('#speed1').val();
    setSpeed(newSpeed, stn1);
  });

  $("#speed2").on('input', function() {
    newSpeed = $('#speed2').val();
    setSpeed(newSpeed, stn2);
  });

  $("#gain1").on('input', function() {
    newGain = $('#gain1').val();
    if (newGain > 100) {
      newGain = 100;
      $("#gain1").val(newGain);
    }
    setGain(newgain, stn1);
  });

  $("#gain2").on('input', function() {
    newGain = $('#gain2').val();
    if (newGain > 100) {
      newGain = 100;
      $("#gain2").val(newGain);
    }
    setGain(newGain, stn2);
  });

  $("#noise").change(function() {
    noise.setEnabled(this.checked);
  });

  $("#noise_gain").on('input', function() {
    newGain = $('#noise_gain').val();
    if (newGain > 100) {
      newGain = 100;
      $("#noise_gain").val(newGain);
    }
    setNoiseGain(newGain);
  });
});
<|endoftext|>


<commit_before>var util = require('util'),
    webutil = require('../util/web'),
    Tab = require('../client/tab').Tab,
    Amount = ripple.Amount;

var SendTab = function ()
{
  Tab.call(this);

  this.on('retrigger', this.handleRetrigger.bind(this));
};

util.inherits(SendTab, Tab);

SendTab.prototype.mainMenu = 'send';

SendTab.prototype.generateHtml = function ()
{
  return require('../../jade/tabs/send.jade')();
};

SendTab.prototype.angular = function (module)
{
  var self = this,
      app = this.app;

  module.controller('SendCtrl', ['$scope', '$timeout', '$routeParams', 'rpId',
                                 function ($scope, $timeout, $routeParams, $id)
  {
    if (!$id.loginStatus) return $id.goId();

    $scope.xrp = $scope.currencies_all[0];

    $scope.$watch('send.recipient', function(){
      var addr = webutil.stripRippleAddress($scope.send.recipient);

      $scope.contact = webutil.getContact($scope.userBlob.data.contacts,addr);
      if ($scope.contact) {
        $scope.send.recipient_name = $scope.contact.name;
        $scope.send.recipient_address = $scope.contact.address;
      } else {
        $scope.send.recipient_name = '';
        $scope.send.recipient_address = addr;
      }

      $scope.update_send();
    }, true);

    $scope.$watch('send.amount', function () {
      $scope.update_send();
    }, true);

    $scope.$watch('send.currency', function () {
      $scope.update_send();
    }, true);

    var pathUpdateTimeout;
    $scope.update_send = function () {
      var currency = $scope.send.currency ?
            $scope.send.currency.slice(0, 3).toUpperCase() : "XRP";
      var recipient = $scope.send.recipient_address;
      var formatted = "" + $scope.send.amount + " " + currency.slice(0, 3);

      if (recipient || currency === "XRP") {
        $scope.send.amount_feedback = Amount.from_human(formatted);

        if (recipient) $scope.send.amount_feedback.set_issuer(recipient);
      } else {
        $scope.send.amount_feedback = new Amount(); // = NaN
      }

      var modified = $scope.send.recipient_prev !== recipient ||
        !$scope.send.amount_prev.is_valid() ||
        !$scope.send.amount_feedback.is_valid() ||
        !$scope.send.amount_feedback.equals($scope.send.amount_prev);

      if (!modified) return;

      $scope.send.recipient_prev = recipient;
      $scope.send.amount_prev = $scope.send.amount_feedback;

      if (recipient && $scope.send.amount_feedback.is_valid()) {
        $scope.send.path_status = 'pending';

        $scope.send.path_sets = null;
        $scope.send.alt = null;

        if ($scope.send.amount_feedback.is_native()) {
          $scope.send.path_status = 'native';
        } else {
          if (pathUpdateTimeout) clearTimeout(pathUpdateTimeout);
          pathUpdateTimeout = setTimeout($scope.update_paths, 500);
        }
      } else {
        $scope.send.path_status = 'waiting';
      }
    };

    $scope.update_paths = function () {
      var recipient = $scope.send.recipient_address;

      app.net.remote.request_ripple_path_find(app.id.account,
                                              $scope.send.recipient_address,
                                              $scope.send.amount_feedback)
        .on('error', function (e) {
          $scope.$apply(function () {
            $scope.path_status = "error";
          });
        })
        .on('success', function (data) {
          $scope.$apply(function () {
            if (!data.alternatives || !data.alternatives.length) {
              $scope.send.path_status = "no-path";
            } else {
              $scope.send.path_status = "done";
              $scope.send.alternatives = _.map(data.alternatives, function (raw) {
                var alt = {};
                alt.amount = Amount.from_json(raw.source_amount);
                alt.send_max = alt.amount.product_human(Amount.from_json('1.01'));
                alt.paths = raw.paths_computed
                  ? raw.paths_computed
                  : raw.paths_canonical;

                return alt;
              });
              $scope.send.alt = $scope.send.alternatives[0];
            }
          });
        })
        .request();
    };

    $scope.$watch('userBlob.data.contacts', function (contacts) {
      $scope.recipient_query = webutil.queryFromOptions(contacts);
    }, true);
    $scope.currency_query = webutil.queryFromOptions($scope.currencies_all);
    $scope.$watch('lines', function (lines) {
      var currencies = _.uniq(_.map(_.keys(lines), function (line) {
        return line.slice(-3);
      }));

      // XXX Not the fastest way of doing it...
      currencies = _.map(currencies, function (currency) {
        _.each($scope.currencies_all, function (entry) {
          if (currency === entry.value) {
            currency = entry.name;
            return false;
          }
        });
        return currency;
      });
      $scope.source_currency_query = webutil.queryFromArray(currencies);
    }, true);

    $scope.reset = function () {
      $scope.mode = "form";

      // XXX Most of these variables should be properties of $scope.send.
      //     The Angular devs recommend that models be objects due to the way
      //     scope inheritance works.
      $scope.send = {
        recipient: '',
        recipient_name: '',
        recipient_address: '',
        recipient_prev: '',
        amount: '',
        amount_prev: new Amount(),
        currency: $scope.xrp.name,
        path_status: 'waiting'
      };
      $scope.nickname = '';
      $scope.error_type = '';
      $scope.resetAddressForm();
      if ($scope.sendForm) $scope.sendForm.$setPristine(true);

      // Focus on first input
      setImmediate(function() {
        $('#sendForm').find('input:first').focus();
      });
    };

    $scope.resetAddressForm = function() {
      $scope.show_save_address_form = false;
      $scope.addressSaved = false;
      $scope.saveAddressName = '';
      $scope.addressSaving = false;
      if ($scope.saveAddressForm) $scope.saveAddressForm.$setPristine(true);
    };

    self.on('reset', $scope.reset);

    $scope.reset_goto = function (tabName) {
      $scope.reset();

      // TODO do something clever instead of document.location
      // because goToTab does $scope.$digest() which we don't need
      document.location = '#' + tabName;
    };

    /**
     * N2. Waiting for path page
     */
    $scope.calculate_send = function () {
      var amount = $scope.send.amount_feedback;
      $scope.sendmax_feedback = null;
      $scope.prepared_paths = null;

      $scope.mode = "wait_path";

      app.net.remote.request_account_info($scope.send.recipient_address)
        .on('error', function (data) {
          $scope.$apply(function () {
            $scope.mode = "error";
            if (data.error === "remoteError" &&
                data.remote.error === "actNotFound") {
              if (amount.is_native()) {
                // XXX Show info about creating accounts, reserve reqs etc.
                $scope.send_prepared();
              } else {
                $scope.error_type = "noDest";
              }
            }
          });
        })
        .on('success', function (data) {
          if (amount.is_native() && !$scope.send.source_currency) {
            $scope.$apply($scope.send_prepared);
          } else {
            app.net.remote.request_ripple_path_find(app.id.account,
                                                    $scope.send.recipient_address,
                                                    amount)
            // XXX Handle error response
              .on('success', function (data) {
                $scope.$apply(function () {
                  if (!data.alternatives || !data.alternatives.length) {
                    $scope.mode = "error";
                    $scope.error_type = "noPath";
                  } else {
                    var base_amount = Amount.from_json(data.alternatives[0].source_amount);
                    $scope.sendmax_feedback =
                      base_amount.product_human(Amount.from_json('1.01'));
                    $scope.prepared_paths = data.alternatives[0].paths_computed
                      ? data.alternatives[0].paths_computed
                      : data.alternatives[0].paths_canonical;
                    $scope.send_prepared();
                  }
                });
              })
              .request();

          }
        })
        .request();
    };

    /**
     * N3. Confirmation page
     */
    $scope.send_prepared = function () {
      $scope.confirm_wait = true;
      $timeout(function () {
        $scope.confirm_wait = false;
        $scope.$digest();
      }, 1000);

      $scope.mode = "confirm";
    };

    /**
     * N4. Waiting for transaction result page
     */
    $scope.send_confirmed = function () {
      var currency = $scope.send.currency.slice(0, 3).toUpperCase();
      var amount = Amount.from_human(""+$scope.send.amount+" "+currency);
      var addr = $scope.send.recipient_address;
      var dt = $routeParams.dt ? $routeParams.dt : webutil.getDestTagFromAddress($scope.send.recipient);

      amount.set_issuer(addr);

      var tx = app.net.remote.transaction();

      // Destination tag
      tx.destination_tag(dt);

      // Source tag
      if ($routeParams.st) {
        tx.source_tag($routeParams.st);
      }

      tx.payment(app.id.account, addr, amount.to_json());
      if (!amount.is_native()) {
        if ($scope.send.alt) {
          tx.send_max($scope.send.alt.send_max);
          tx.paths($scope.send.alt.paths);
        } else {
          tx.build_path(true);
        }
      }
      tx.on('success', function (res) {
        setEngineStatus(res, false);
        $scope.sent(this.hash);
        $scope.$digest();
      });
      tx.on('error', function (res) {
        setImmediate(function () {
          $scope.mode = "error";

          if (res.error === 'remoteError' &&
              res.remote.error === 'noPath') {
            $scope.mode = "status";
            $scope.tx_result = "noPath";
          }
          $scope.$digest();
        });
      });
      tx.submit();

      $scope.mode = "sending";
    };

    /**
     * N6. Sent page
     */
    $scope.sent = function (hash) {
      $scope.mode = "status";
      app.net.remote.on('account', handleAccountEvent);

      function handleAccountEvent(e) {
        if (e.transaction.hash === hash) {
          setEngineStatus(e, true);
          $scope.$digest();
          app.net.remote.removeListener('account', handleAccountEvent);
        }
      }
    };

    function setEngineStatus(res, accepted) {
      $scope.engine_result = res.engine_result;
      $scope.engine_result_message = res.engine_result_message;
      switch (res.engine_result.slice(0, 3)) {
        case 'tes':
          $scope.tx_result = accepted ? "cleared" : "pending";
          break;
        case 'tem':
          $scope.tx_result = "malformed";
          break;
        case 'ter':
          $scope.tx_result = "failed";
          break;
        case 'tep':
          $scope.tx_result = "partial";
          break;
        case 'tec':
          $scope.tx_result = "claim";
          break;
        default:
          console.warn("Unhandled engine status encountered!");
      }
    }

    $scope.saveAddress = function () {
      $scope.addressSaving = true;

      var contact = {
        'name': $scope.saveAddressName,
        'address': $scope.send.recipient_address
      }

      app.id.once('blobsave', function(){
        $scope.contact = contact;
        $scope.addressSaved = true;
      })

      app.$scope.userBlob.data.contacts.unshift(contact);
    }

    $scope.reset();

    // If all the form fields are prefilled, go to confirmation page
    if ($routeParams.to && $routeParams.amount) {
      setImmediate(function() {
        $scope.calculate_send();
      });
    }
  }]);

  /**
   * Contact name and address uniqueness validator
   */
  // TODO move to global directives
  module.directive('unique', function() {
    return {
      restrict: 'A',
      require: '?ngModel',
      link: function ($scope, elm, attr, ctrl) {
        if (!ctrl) return;

        var validator = function(value) {
          if (!webutil.getContact($scope.userBlob.data.contacts,value)) {
            ctrl.$setValidity('unique', true);
            return value;
          } else {
            ctrl.$setValidity('unique', false);
            return;
          }
        };

        ctrl.$formatters.push(validator);
        ctrl.$parsers.unshift(validator);

        attr.$observe('unique', function() {
          validator(ctrl.$viewValue);
        });
      }
    };
  });

  /**
   * Don't allow the user to send XRP to himself
   */
  module.directive('rpXrpToMe', function () {
    return {
      restrict: 'A',
      require: '?ngModel',
      link: function (scope, elm, attr, ctrl) {
        console.log(elm.inheritedData('$formController'));
        var xrpWidget = elm.inheritedData('$formController')[attr.rpXrpToMe];

        ctrl.$parsers.unshift(function(value) {
          var contact = webutil.getContact(scope.userBlob.data.contacts,value);

          if (value) {
            if ((contact && contact.address == scope.userBlob.data.account_id) || scope.userBlob.data.account_id == value) {
              if (scope.send.currency == xrpWidget.$viewValue) {
                ctrl.$setValidity('rpXrpToMe', false);
                return;
              }
            }
          }

          ctrl.$setValidity('rpXrpToMe', true);
          return value;
        });

        xrpWidget.$parsers.unshift(function(value) {
          ctrl.$setValidity('rpXrpToMe', value === ctrl.$viewValue);
          return value;
        });
      }
    };
  });
}

SendTab.prototype.handleRetrigger = function () {
  var $scope = $('#t-send').data('$scope');
  if ($scope && $scope.mode !== 'form') {
    $scope.reset();
    $scope.$digest();
  }
};

module.exports = SendTab;
<commit_msg>Send page prefill can no longer (trivially) jump straight to confirmation page.<commit_after>var util = require('util'),
    webutil = require('../util/web'),
    Tab = require('../client/tab').Tab,
    Amount = ripple.Amount;

var SendTab = function ()
{
  Tab.call(this);

  this.on('retrigger', this.handleRetrigger.bind(this));
};

util.inherits(SendTab, Tab);

SendTab.prototype.mainMenu = 'send';

SendTab.prototype.generateHtml = function ()
{
  return require('../../jade/tabs/send.jade')();
};

SendTab.prototype.angular = function (module)
{
  var self = this,
      app = this.app;

  module.controller('SendCtrl', ['$scope', '$timeout', '$routeParams', 'rpId',
                                 function ($scope, $timeout, $routeParams, $id)
  {
    if (!$id.loginStatus) return $id.goId();

    $scope.xrp = $scope.currencies_all[0];

    $scope.$watch('send.recipient', function(){
      var addr = webutil.stripRippleAddress($scope.send.recipient);

      $scope.contact = webutil.getContact($scope.userBlob.data.contacts,addr);
      if ($scope.contact) {
        $scope.send.recipient_name = $scope.contact.name;
        $scope.send.recipient_address = $scope.contact.address;
      } else {
        $scope.send.recipient_name = '';
        $scope.send.recipient_address = addr;
      }

      $scope.update_send();
    }, true);

    $scope.$watch('send.amount', function () {
      $scope.update_send();
    }, true);

    $scope.$watch('send.currency', function () {
      $scope.update_send();
    }, true);

    var pathUpdateTimeout;
    $scope.update_send = function () {
      var currency = $scope.send.currency ?
            $scope.send.currency.slice(0, 3).toUpperCase() : "XRP";
      var recipient = $scope.send.recipient_address;
      var formatted = "" + $scope.send.amount + " " + currency.slice(0, 3);

      if (recipient || currency === "XRP") {
        $scope.send.amount_feedback = Amount.from_human(formatted);

        if (recipient) $scope.send.amount_feedback.set_issuer(recipient);
      } else {
        $scope.send.amount_feedback = new Amount(); // = NaN
      }

      var modified = $scope.send.recipient_prev !== recipient ||
        !$scope.send.amount_prev.is_valid() ||
        !$scope.send.amount_feedback.is_valid() ||
        !$scope.send.amount_feedback.equals($scope.send.amount_prev);

      if (!modified) return;

      $scope.send.recipient_prev = recipient;
      $scope.send.amount_prev = $scope.send.amount_feedback;

      if (recipient && $scope.send.amount_feedback.is_valid()) {
        $scope.send.path_status = 'pending';

        $scope.send.path_sets = null;
        $scope.send.alt = null;

        if ($scope.send.amount_feedback.is_native()) {
          $scope.send.path_status = 'native';
        } else {
          if (pathUpdateTimeout) clearTimeout(pathUpdateTimeout);
          pathUpdateTimeout = setTimeout($scope.update_paths, 500);
        }
      } else {
        $scope.send.path_status = 'waiting';
      }
    };

    $scope.update_paths = function () {
      var recipient = $scope.send.recipient_address;

      app.net.remote.request_ripple_path_find(app.id.account,
                                              $scope.send.recipient_address,
                                              $scope.send.amount_feedback)
        .on('error', function (e) {
          $scope.$apply(function () {
            $scope.path_status = "error";
          });
        })
        .on('success', function (data) {
          $scope.$apply(function () {
            if (!data.alternatives || !data.alternatives.length) {
              $scope.send.path_status = "no-path";
            } else {
              $scope.send.path_status = "done";
              $scope.send.alternatives = _.map(data.alternatives, function (raw) {
                var alt = {};
                alt.amount = Amount.from_json(raw.source_amount);
                alt.send_max = alt.amount.product_human(Amount.from_json('1.01'));
                alt.paths = raw.paths_computed
                  ? raw.paths_computed
                  : raw.paths_canonical;

                return alt;
              });
              $scope.send.alt = $scope.send.alternatives[0];
            }
          });
        })
        .request();
    };

    $scope.$watch('userBlob.data.contacts', function (contacts) {
      $scope.recipient_query = webutil.queryFromOptions(contacts);
    }, true);
    $scope.currency_query = webutil.queryFromOptions($scope.currencies_all);
    $scope.$watch('lines', function (lines) {
      var currencies = _.uniq(_.map(_.keys(lines), function (line) {
        return line.slice(-3);
      }));

      // XXX Not the fastest way of doing it...
      currencies = _.map(currencies, function (currency) {
        _.each($scope.currencies_all, function (entry) {
          if (currency === entry.value) {
            currency = entry.name;
            return false;
          }
        });
        return currency;
      });
      $scope.source_currency_query = webutil.queryFromArray(currencies);
    }, true);

    $scope.reset = function () {
      $scope.mode = "form";

      // XXX Most of these variables should be properties of $scope.send.
      //     The Angular devs recommend that models be objects due to the way
      //     scope inheritance works.
      $scope.send = {
        recipient: '',
        recipient_name: '',
        recipient_address: '',
        recipient_prev: '',
        amount: '',
        amount_prev: new Amount(),
        currency: $scope.xrp.name,
        path_status: 'waiting'
      };
      $scope.nickname = '';
      $scope.error_type = '';
      $scope.resetAddressForm();
      if ($scope.sendForm) $scope.sendForm.$setPristine(true);

      // Focus on first input
      setImmediate(function() {
        $('#sendForm').find('input:first').focus();
      });
    };

    $scope.resetAddressForm = function() {
      $scope.show_save_address_form = false;
      $scope.addressSaved = false;
      $scope.saveAddressName = '';
      $scope.addressSaving = false;
      if ($scope.saveAddressForm) $scope.saveAddressForm.$setPristine(true);
    };

    self.on('reset', $scope.reset);

    $scope.reset_goto = function (tabName) {
      $scope.reset();

      // TODO do something clever instead of document.location
      // because goToTab does $scope.$digest() which we don't need
      document.location = '#' + tabName;
    };

    /**
     * N2. Waiting for path page
     */
    $scope.calculate_send = function () {
      var amount = $scope.send.amount_feedback;
      $scope.sendmax_feedback = null;
      $scope.prepared_paths = null;

      $scope.mode = "wait_path";

      app.net.remote.request_account_info($scope.send.recipient_address)
        .on('error', function (data) {
          $scope.$apply(function () {
            $scope.mode = "error";
            if (data.error === "remoteError" &&
                data.remote.error === "actNotFound") {
              if (amount.is_native()) {
                // XXX Show info about creating accounts, reserve reqs etc.
                $scope.send_prepared();
              } else {
                $scope.error_type = "noDest";
              }
            }
          });
        })
        .on('success', function (data) {
          if (amount.is_native() && !$scope.send.source_currency) {
            $scope.$apply($scope.send_prepared);
          } else {
            app.net.remote.request_ripple_path_find(app.id.account,
                                                    $scope.send.recipient_address,
                                                    amount)
            // XXX Handle error response
              .on('success', function (data) {
                $scope.$apply(function () {
                  if (!data.alternatives || !data.alternatives.length) {
                    $scope.mode = "error";
                    $scope.error_type = "noPath";
                  } else {
                    var base_amount = Amount.from_json(data.alternatives[0].source_amount);
                    $scope.sendmax_feedback =
                      base_amount.product_human(Amount.from_json('1.01'));
                    $scope.prepared_paths = data.alternatives[0].paths_computed
                      ? data.alternatives[0].paths_computed
                      : data.alternatives[0].paths_canonical;
                    $scope.send_prepared();
                  }
                });
              })
              .request();

          }
        })
        .request();
    };

    /**
     * N3. Confirmation page
     */
    $scope.send_prepared = function () {
      $scope.confirm_wait = true;
      $timeout(function () {
        $scope.confirm_wait = false;
        $scope.$digest();
      }, 1000);

      $scope.mode = "confirm";
    };

    /**
     * N4. Waiting for transaction result page
     */
    $scope.send_confirmed = function () {
      var currency = $scope.send.currency.slice(0, 3).toUpperCase();
      var amount = Amount.from_human(""+$scope.send.amount+" "+currency);
      var addr = $scope.send.recipient_address;
      var dt = $routeParams.dt ? $routeParams.dt : webutil.getDestTagFromAddress($scope.send.recipient);

      amount.set_issuer(addr);

      var tx = app.net.remote.transaction();

      // Destination tag
      tx.destination_tag(dt);

      // Source tag
      if ($routeParams.st) {
        tx.source_tag($routeParams.st);
      }

      tx.payment(app.id.account, addr, amount.to_json());
      if (!amount.is_native()) {
        if ($scope.send.alt) {
          tx.send_max($scope.send.alt.send_max);
          tx.paths($scope.send.alt.paths);
        } else {
          tx.build_path(true);
        }
      }
      tx.on('success', function (res) {
        setEngineStatus(res, false);
        $scope.sent(this.hash);
        $scope.$digest();
      });
      tx.on('error', function (res) {
        setImmediate(function () {
          $scope.mode = "error";

          if (res.error === 'remoteError' &&
              res.remote.error === 'noPath') {
            $scope.mode = "status";
            $scope.tx_result = "noPath";
          }
          $scope.$digest();
        });
      });
      tx.submit();

      $scope.mode = "sending";
    };

    /**
     * N6. Sent page
     */
    $scope.sent = function (hash) {
      $scope.mode = "status";
      app.net.remote.on('account', handleAccountEvent);

      function handleAccountEvent(e) {
        if (e.transaction.hash === hash) {
          setEngineStatus(e, true);
          $scope.$digest();
          app.net.remote.removeListener('account', handleAccountEvent);
        }
      }
    };

    function setEngineStatus(res, accepted) {
      $scope.engine_result = res.engine_result;
      $scope.engine_result_message = res.engine_result_message;
      switch (res.engine_result.slice(0, 3)) {
        case 'tes':
          $scope.tx_result = accepted ? "cleared" : "pending";
          break;
        case 'tem':
          $scope.tx_result = "malformed";
          break;
        case 'ter':
          $scope.tx_result = "failed";
          break;
        case 'tep':
          $scope.tx_result = "partial";
          break;
        case 'tec':
          $scope.tx_result = "claim";
          break;
        default:
          console.warn("Unhandled engine status encountered!");
      }
    }

    $scope.saveAddress = function () {
      $scope.addressSaving = true;

      var contact = {
        'name': $scope.saveAddressName,
        'address': $scope.send.recipient_address
      }

      app.id.once('blobsave', function(){
        $scope.contact = contact;
        $scope.addressSaved = true;
      })

      app.$scope.userBlob.data.contacts.unshift(contact);
    }

    $scope.reset();
  }]);

  /**
   * Contact name and address uniqueness validator
   */
  // TODO move to global directives
  module.directive('unique', function() {
    return {
      restrict: 'A',
      require: '?ngModel',
      link: function ($scope, elm, attr, ctrl) {
        if (!ctrl) return;

        var validator = function(value) {
          if (!webutil.getContact($scope.userBlob.data.contacts,value)) {
            ctrl.$setValidity('unique', true);
            return value;
          } else {
            ctrl.$setValidity('unique', false);
            return;
          }
        };

        ctrl.$formatters.push(validator);
        ctrl.$parsers.unshift(validator);

        attr.$observe('unique', function() {
          validator(ctrl.$viewValue);
        });
      }
    };
  });

  /**
   * Don't allow the user to send XRP to himself
   */
  module.directive('rpXrpToMe', function () {
    return {
      restrict: 'A',
      require: '?ngModel',
      link: function (scope, elm, attr, ctrl) {
        console.log(elm.inheritedData('$formController'));
        var xrpWidget = elm.inheritedData('$formController')[attr.rpXrpToMe];

        ctrl.$parsers.unshift(function(value) {
          var contact = webutil.getContact(scope.userBlob.data.contacts,value);

          if (value) {
            if ((contact && contact.address == scope.userBlob.data.account_id) || scope.userBlob.data.account_id == value) {
              if (scope.send.currency == xrpWidget.$viewValue) {
                ctrl.$setValidity('rpXrpToMe', false);
                return;
              }
            }
          }

          ctrl.$setValidity('rpXrpToMe', true);
          return value;
        });

        xrpWidget.$parsers.unshift(function(value) {
          ctrl.$setValidity('rpXrpToMe', value === ctrl.$viewValue);
          return value;
        });
      }
    };
  });
}

SendTab.prototype.handleRetrigger = function () {
  var $scope = $('#t-send').data('$scope');
  if ($scope && $scope.mode !== 'form') {
    $scope.reset();
    $scope.$digest();
  }
};

module.exports = SendTab;
<|endoftext|>


<commit_before>var isInScrollBar = function(canvas, context, x, y){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	return x > canvas.width - width && y > distanceFromTop && y < distanceFromTop + height;
}

var getScrollPositionFromScrollBar = function(canvas, context, y, maxScroll){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	return (y - distanceFromTop) * maxScroll / height;
}

var drawScrollBar = function(canvas, context, scrollPosition, maxScroll){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	context.strokeStyle=staveColour;
	context.rect(canvas.width - width, distanceFromTop, width, height);
	context.stroke();

	context.beginPath();
	context.strokeStyle=noteColour;
	context.lineWidth =4;
	context.moveTo(canvas.width - width, scrollPosition * height / maxScroll + distanceFromTop);
	context.lineTo(canvas.width, scrollPosition * height / maxScroll + distanceFromTop);
	context.stroke();
	context.lineWidth = 1;
}

var drawScrollPreview = function(canvas, context, y){
	var rightMargin = 20;
	var width = 50;
	var farLeft = canvas.width - (rightMargin + width) - 12;

	context.beginPath();
	context.moveTo(farLeft, y);
	context.lineTo(farLeft + width, y);
	context.lineTo(farLeft + width - 10, y + 5)
	context.lineTo(farLeft + width - 10, y + 50);
	context.lineTo(farLeft, y + 50);
	context.lineTo(farLeft, y);
	context.stroke();
	context.fillStyle="white";
	context.fill();
}
<commit_msg>Update scrollbar.js<commit_after>var isInScrollBar = function(canvas, context, x, y){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	return x > canvas.width - width && y > distanceFromTop && y < distanceFromTop + height;
}

var getScrollPositionFromScrollBar = function(canvas, context, y, maxScroll){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	return (y - distanceFromTop) * maxScroll / height;
}

var drawScrollBar = function(canvas, context, scrollPosition, maxScroll){
	var height = 400;
	var width = 20;
	var distanceFromTop = 100;

	context.strokeStyle=staveColour;
	context.rect(canvas.width - width, distanceFromTop, width, height);
	context.stroke();

	context.beginPath();
	context.strokeStyle=noteColour;
	context.lineWidth =4;
	context.moveTo(canvas.width - width, scrollPosition * height / maxScroll + distanceFromTop);
	context.lineTo(canvas.width, scrollPosition * height / maxScroll + distanceFromTop);
	context.stroke();
	context.lineWidth = 1;
}

var drawScrollPreview = function(canvas, context, y){
	var rightMargin = 20;
	var width = 50;
	var farLeft = canvas.width - (rightMargin + width) - 12;

	context.beginPath();
	context.moveTo(farLeft, y);
	context.lineTo(farLeft + width + 10, y);
	context.lineTo(farLeft + width, y + 5)
	context.lineTo(farLeft + width, y + 50);
	context.lineTo(farLeft, y + 50);
	context.lineTo(farLeft, y);
	context.stroke();
	context.fillStyle="white";
	context.fill();
}
<|endoftext|>


<commit_before>'use strict';

const test = require('tape');
const getCalendarStructure = require('../lib/getCalendarStructure');
const datetime = require('../lib/datetime');

test('get calendar structure', (assert) => {
  let bookableMonths = [datetime('2015-12')];

  let availableDates =
  {
    "2015-12-04": {
      "calendar_id": "1228",
      "available_times_count": 20
    },
    "2015-12-28": {
      "calendar_id": "1229",
      "available_times_count": 6
    }
  };

  let calendarStructure = getCalendarStructure(bookableMonths, availableDates);

  let expectedStructure =
  {
    "months": [
      {
        "month": "2015-12",
        "monthName": "December",
        "weeks": [
          {
            "days": [
              {
                date: "2015-11-30",
                day: 30,
                available_times_count: 0
              },
              {
                date: "2015-12-01",
                day: 1,
                available_times_count: 0
              },
              {
                date: "2015-12-02",
                day: 2,
                available_times_count: 0
              },
              {
                date: "2015-12-03",
                day: 3,
                available_times_count: 0
              },
              {
                date: "2015-12-04",
                day: 4,
                available_times_count: 20
              },
              {
                date: "2015-12-05",
                day: 5,
                available_times_count: 0
              },
              {
                date: "2015-12-06",
                day: 6,
                available_times_count: 0
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-07",
                day: 7,
                available_times_count: 0
              },
              {
                date: "2015-12-08",
                day: 8,
                available_times_count: 0
              },
              {
                date: "2015-12-09",
                day: 9,
                available_times_count: 0
              },
              {
                date: "2015-12-10",
                day: 10,
                available_times_count: 0
              },
              {
                date: "2015-12-11",
                day: 11,
                available_times_count: 0
              },
              {
                date: "2015-12-12",
                day: 12,
                available_times_count: 0
              },
              {
                date: "2015-12-13",
                day: 13,
                available_times_count: 0
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-14",
                day: 14,
                available_times_count: 0
              },
              {
                date: "2015-12-15",
                day: 15,
                available_times_count: 0
              },
              {
                date: "2015-12-16",
                day: 16,
                available_times_count: 0
              },
              {
                date: "2015-12-17",
                day: 17,
                available_times_count: 0
              },
              {
                date: "2015-12-18",
                day: 18,
                available_times_count: 0
              },
              {
                date: "2015-12-19",
                day: 19,
                available_times_count: 0
              },
              {
                date: "2015-12-20",
                day: 20,
                available_times_count: 0
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-21",
                day: 21,
                available_times_count: 0
              },
              {
                date: "2015-12-22",
                day: 22,
                available_times_count: 0
              },
              {
                date: "2015-12-23",
                day: 23,
                available_times_count: 0
              },
              {
                date: "2015-12-24",
                day: 24,
                available_times_count: 0
              },
              {
                date: "2015-12-25",
                day: 25,
                available_times_count: 0
              },
              {
                date: "2015-12-26",
                day: 26,
                available_times_count: 0
              },
              {
                date: "2015-12-27",
                day: 27,
                available_times_count: 0
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-28",
                day: 28,
                available_times_count: 6
              },
              {
                date: "2015-12-29",
                day: 29,
                available_times_count: 0
              },
              {
                date: "2015-12-30",
                day: 30,
                available_times_count: 0
              },
              {
                date: "2015-12-31",
                day: 31,
                available_times_count: 0
              },
              {
                date: "2016-01-01",
                day: 1,
                available_times_count: 0
              },
              {
                date: "2016-01-02",
                day: 2,
                available_times_count: 0
              },
              {
                date: "2016-01-03",
                day: 3,
                available_times_count: 0
              }
            ]
          }
        ]
      }
    ]
  }

  assert.deepEqual(JSON.stringify(calendarStructure), JSON.stringify(expectedStructure));
  assert.end();
})
;
<commit_msg>Fix test<commit_after>'use strict';

const test = require('tape');
const getCalendarStructure = require('../lib/getCalendarStructure');
const datetime = require('../lib/datetime');

test('get calendar structure', (assert) => {
  let bookableMonths = [datetime('2015-12')];

  let availableDates =
  {
    "2015-12-04": {
      "calendar_id": "1228",
      "available_times_count": 20
    },
    "2015-12-28": {
      "calendar_id": "1229",
      "available_times_count": 6
    }
  };

  let calendarStructure = getCalendarStructure(bookableMonths, availableDates);

  let expectedStructure =
  {
    "months": [
      {
        "month": "2015-12",
        "monthName": "December",
        "weeks": [
          {
            "days": [
              {
                date: "2015-11-30",
                today: false,
                day: 30,
                available_times_count: 0,
                bookable: false
              },
              {
                date: "2015-12-01",
                today: false,
                day: 1,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-02",
                today: false,
                day: 2,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-03",
                today: false,
                day: 3,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-04",
                today: false,
                day: 4,
                available_times_count: 20,
                bookable: true
              },
              {
                date: "2015-12-05",
                today: false,
                day: 5,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-06",
                today: false,
                day: 6,
                available_times_count: 0,
                bookable: true
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-07",
                today: false,
                day: 7,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-08",
                today: false,
                day: 8,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-09",
                today: false,
                day: 9,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-10",
                today: false,
                day: 10,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-11",
                today: false,
                day: 11,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-12",
                today: false,
                day: 12,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-13",
                today: false,
                day: 13,
                available_times_count: 0,
                bookable: true
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-14",
                today: false,
                day: 14,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-15",
                today: false,
                day: 15,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-16",
                today: false,
                day: 16,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-17",
                today: false,
                day: 17,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-18",
                today: false,
                day: 18,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-19",
                today: false,
                day: 19,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-20",
                today: false,
                day: 20,
                available_times_count: 0,
                bookable: true
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-21",
                today: false,
                day: 21,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-22",
                today: false,
                day: 22,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-23",
                today: false,
                day: 23,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-24",
                today: false,
                day: 24,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-25",
                today: false,
                day: 25,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-26",
                today: false,
                day: 26,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-27",
                today: false,
                day: 27,
                available_times_count: 0,
                bookable: true
              }
            ]
          },
          {
            days: [
              {
                date: "2015-12-28",
                today: false,
                day: 28,
                available_times_count: 6,
                bookable: true
              },
              {
                date: "2015-12-29",
                today: false,
                day: 29,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-30",
                today: false,
                day: 30,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2015-12-31",
                today: false,
                day: 31,
                available_times_count: 0,
                bookable: true
              },
              {
                date: "2016-01-01",
                today: false,
                day: 1,
                available_times_count: 0,
                bookable: false
              },
              {
                date: "2016-01-02",
                today: false,
                day: 2,
                available_times_count: 0,
                bookable: false
              },
              {
                date: "2016-01-03",
                today: false,
                day: 3,
                available_times_count: 0,
                bookable: false
              }
            ]
          }
        ]
      }
    ]
  }

  assert.deepEqual(calendarStructure, expectedStructure);
  assert.end();
})
;
<|endoftext|>


<commit_before>var Cimpler  = require('../lib/cimpler'),
    GCS      = require('../plugins/github-commit-status'),
    assert   = require('assert');

describe("Github commit status plugin", function() {
   describe("authentication", function() {
      it("should pass the 'auth' config object straight through", function() {
         var auth = {a: 1},
         cimpler = new Cimpler(),
         GH = newApi();

         cimpler.registerPlugin(GCS, {
            auth: auth,
            _overrideApi: GH
         });

         assert.equal(GH.collected.auth, auth);
      });
   });

   it("started then finished", function(done) {
      var build = {
         repo: "git://github.com/user/repo.git",
         status: 'BLAH',
         commit: '11111',
         logUrl: 'http'
      };

      sendBuild(assert, build, function(statuses) {
         assert.equal(statuses.length, 2);

         var status = {
            user: 'user',
            repo: 'repo',
            commit: build.commit,
            state: 'pending',
            target_url: build.logUrl,
            description: 'Build Started' };
         assert.deepEqual(statuses[0], status);
         status.description = "Build BLAH";
         status.state = 'BLAH';
         assert.deepEqual(statuses[1], status);
         done();
      });
   });

   describe("build errors", function() {
      it("should emit an error commit status", function(done) {
         var build = {
            repo: "git://github.com:user/repo.git",
            status: 'BLAH',
            commit: '11111',
            logUrl: 'http',
            error: "ERR"
         };
         sendBuild(assert, build, function(statuses) {
            assert.equal(statuses.length, 2);

            var status = {
               user: 'user',
               repo: 'repo',
               commit: build.commit,
               state: 'pending',
               target_url: build.logUrl,
               description: 'Build Started' };

            assert.deepEqual(statuses[0], status);
            // The status for 'finished' will be 'error' if build.error
            status.description = "ERR";
            status.state = 'error';
            assert.deepEqual(statuses[1], status);
            done();
         });
      });
   });
});

/**
 * Passes a build throught thestarted/finished phase and collect the commit
 * status API calls.
 */
function sendBuild(assert, build, callback) {
   var cimpler = new Cimpler(),
   startedBuild = false,
   GH = newApi();

   cimpler.registerPlugin(GCS, {
      _overrideApi: GH
   });

   var statuses = GH.collected.statuses;
   assert.equal(statuses.length, 0);

   cimpler.addBuild(build);

   cimpler.consumeBuild(function(build, started, finished) {
      assert.equal(statuses.length, 0);
      started();

      later(function() {
         assert.equal(statuses.length, 1);
         finished();
      });
   });

   cimpler.on('buildFinished', function(build) {
      later(function() {
         assert.equal(statuses.length, 2);
         callback(GH.collected.statuses);
      });
   });
}

function newApi() {
   var info = {
      statuses: []
   };

   function ghAPI() {
      this.statuses = {
         create: function(status) {
            info.statuses.push(status);
         }
      };

      this.authenticate = function(auth) {
         info.auth = auth;
      };
   }

   ghAPI.collected = info;
   return ghAPI;
}

function later(callback) {
   process.nextTick(function() {
      process.nextTick(callback);
   });
}
<commit_msg>Tests: fix commit -> sha usage<commit_after>var Cimpler  = require('../lib/cimpler'),
    GCS      = require('../plugins/github-commit-status'),
    assert   = require('assert');

describe("Github commit status plugin", function() {
   describe("authentication", function() {
      it("should pass the 'auth' config object straight through", function() {
         var auth = {a: 1},
         cimpler = new Cimpler(),
         GH = newApi();

         cimpler.registerPlugin(GCS, {
            auth: auth,
            _overrideApi: GH
         });

         assert.equal(GH.collected.auth, auth);
      });
   });

   it("started then finished", function(done) {
      var build = {
         repo: "git://github.com/user/repo.git",
         status: 'BLAH',
         commit: '11111',
         logUrl: 'http'
      };

      sendBuild(assert, build, function(statuses) {
         assert.equal(statuses.length, 2);

         var status = {
            user: 'user',
            repo: 'repo',
            sha: build.commit,
            state: 'pending',
            target_url: build.logUrl,
            description: 'Build Started' };
         assert.deepEqual(statuses[0], status);
         status.description = "Build BLAH";
         status.state = 'BLAH';
         assert.deepEqual(statuses[1], status);
         done();
      });
   });

   describe("build errors", function() {
      it("should emit an error commit status", function(done) {
         var build = {
            repo: "git://github.com:user/repo.git",
            status: 'BLAH',
            commit: '11111',
            logUrl: 'http',
            error: "ERR"
         };
         sendBuild(assert, build, function(statuses) {
            assert.equal(statuses.length, 2);

            var status = {
               user: 'user',
               repo: 'repo',
               sha: build.commit,
               state: 'pending',
               target_url: build.logUrl,
               description: 'Build Started' };

            assert.deepEqual(statuses[0], status);
            // The status for 'finished' will be 'error' if build.error
            status.description = "ERR";
            status.state = 'error';
            assert.deepEqual(statuses[1], status);
            done();
         });
      });
   });
});

/**
 * Passes a build throught thestarted/finished phase and collect the commit
 * status API calls.
 */
function sendBuild(assert, build, callback) {
   var cimpler = new Cimpler(),
   startedBuild = false,
   GH = newApi();

   cimpler.registerPlugin(GCS, {
      _overrideApi: GH
   });

   var statuses = GH.collected.statuses;
   assert.equal(statuses.length, 0);

   cimpler.addBuild(build);

   cimpler.consumeBuild(function(build, started, finished) {
      assert.equal(statuses.length, 0);
      started();

      later(function() {
         assert.equal(statuses.length, 1);
         finished();
      });
   });

   cimpler.on('buildFinished', function(build) {
      later(function() {
         assert.equal(statuses.length, 2);
         callback(GH.collected.statuses);
      });
   });
}

function newApi() {
   var info = {
      statuses: []
   };

   function ghAPI() {
      this.statuses = {
         create: function(status) {
            info.statuses.push(status);
         }
      };

      this.authenticate = function(auth) {
         info.auth = auth;
      };
   }

   ghAPI.collected = info;
   return ghAPI;
}

function later(callback) {
   process.nextTick(function() {
      process.nextTick(callback);
   });
}
<|endoftext|>


<commit_before>import {expect} from 'chai'

import loadStudent from '../../src/helpers/load-student'
import demoStudent from '../../src/models/demo-student.json'

import mock from 'mock-require'
mock('../../src/helpers/get-courses', require('../mocks/get-courses.mock').default)
mock('../../src/helpers/load-area', require('../mocks/load-area.mock').default)
import Student from '../../src/models/student'

describe('loadStudent', () => {
	let student
	beforeEach(() => {
		student = Student(demoStudent)
		localStorage.clear()
		localStorage.setItem(student.id, JSON.stringify(student))
	})

	it('returns a promise', () => {
		expect(loadStudent(student.id)).to.be.instanceof(Promise)
	})

	it('loads a student', async () => {
		const actual = await loadStudent(student.id)
		expect(actual).to.be.ok
		expect(actual).to.be.an.object
	})

	it(`removes the student if it is null`, async () => {
		localStorage.removeItem(student.id)
		const actual = await loadStudent(student.id)
		expect(actual).to.equal(null)
	})

	it(`removes the student if it is the string [Object object]`, async () => {
		localStorage.setItem(student.id, String(student))
		const actual = await loadStudent(student.id)
		expect(actual).to.equal(null)
	})

	it('returns a fresh student if JSON errors are encountered', async () => {
		localStorage.setItem(student.id, 'hello!')
		const actual = await loadStudent(student.id)
		expect(actual).to.be.an.object
	})
})
<commit_msg>fix loadStudent promise<commit_after>import {expect} from 'chai'

import loadStudent from '../../src/helpers/load-student'
import demoStudent from '../../src/models/demo-student.json'

import mock from 'mock-require'
mock('../../src/helpers/get-courses', require('../mocks/get-courses.mock').default)
mock('../../src/helpers/load-area', require('../mocks/load-area.mock').default)
import Student from '../../src/models/student'

describe('loadStudent', () => {
	let student
	beforeEach(() => {
		student = Student(demoStudent)
		localStorage.clear()
		localStorage.setItem(student.id, JSON.stringify(student))
	})

	it('returns a promise', () => {
		expect(loadStudent(student.id)).to.have.property('then')
	})

	it('loads a student', async () => {
		const actual = await loadStudent(student.id)
		expect(actual).to.be.ok
		expect(actual).to.be.an.object
	})

	it(`removes the student if it is null`, async () => {
		localStorage.removeItem(student.id)
		const actual = await loadStudent(student.id)
		expect(actual).to.equal(null)
	})

	it(`removes the student if it is the string [Object object]`, async () => {
		localStorage.setItem(student.id, String(student))
		const actual = await loadStudent(student.id)
		expect(actual).to.equal(null)
	})

	it('returns a fresh student if JSON errors are encountered', async () => {
		localStorage.setItem(student.id, 'hello!')
		const actual = await loadStudent(student.id)
		expect(actual).to.be.an.object
	})
})
<|endoftext|>