<commit_before>var wfjs = (function () {
var wfjs1 = {};

var SVGNS = "http://www.w3.org/2000/svg";

var TEXT_DEFAULT_OPTIONS = {
	fill : "black",
	"font-size" : "1em",
};

var CIRCLE_DEFAULT_OPTIONS = {
	r: 30,
	stroke: "blue",
	"stroke-width": "2",
	fill: "yellow",
	filter: "url(#dropshadow1)"
};

var DIAMOND_DEFAULT_OPTIONS = {
	stroke: "yellow",
	"stroke-width": "2",
	fill: "DarkSeaGreen",
	width : 60,
	height : 60,
	filter: "url(#dropshadow1)"
};

wfjs1.Canvas = (function () {
	var draggingNode = null;

	var _canvasInstance;
    function Canvas(containerId) {
		_canvasInstance = this;

		var _onMouseUp = function(e){
			if(draggingNode != null){
				draggingNode = null;
			}
		};

		var _onMouseMove = function(e){
			if(draggingNode != null ){
				var x, y;
				if(e.offsetX==undefined){ // Firefox
					x = e.pageX-$(_canvasInstance.svgElement).offset().left;
					y = e.pageY-$(_canvasInstance.svgElement).offset().top;
				}else{ // Chrome
					x = e.offsetX;
					y = e.offsetY;
				}

				draggingNode.move(x, y);
//				draggingNode.move(e.layerX, e.layerY);
//				draggingNode.move(e.x, e.y);
//				console.debug(e.target);
//				console.debug("offsetX: " + e.offsetX + " e.x:" + e.x + " layerX:" + e.layerX);
				console.debug("tag:" + e.target.tagName + " screenY: " + e.screenY + " pageY: " + e.pageY + " clientY: " + e.clientY + " offsetY: " + e.offsetY + " e.y:" + e.y + " layerY:" + e.layerY);
			}
		};

        this.containerId = containerId;
		this.container = document.getElementById(containerId);

		var svgElement = document.createElementNS(SVGNS, "svg");
		svgElement.setAttribute("id", "wfjs_svg");
		svgElement.setAttribute("version", "1.1");
		svgElement.addEventListener("mouseup", _onMouseUp, false);
//		$(svgElement).on('mousemove', _onMouseMove);
		svgElement.addEventListener("mousemove", _onMouseMove, false);

		this.container.appendChild(svgElement);
		this.svgElement = svgElement;

		var defsElement = document.createElementNS(SVGNS, "defs");
		svgElement.appendChild(defsElement);

		var filterElement = document.createElementNS(SVGNS, "filter");
		filterElement.setAttribute("id", "dropshadow1");
		defsElement.appendChild(filterElement);

		var feGaussianBlurElement = document.createElementNS(SVGNS, "feGaussianBlur");
		feGaussianBlurElement.setAttribute("in", "SourceAlpha");
		feGaussianBlurElement.setAttribute("stdDeviation", "3");
		filterElement.appendChild(feGaussianBlurElement);

		var feOffsetElement = document.createElementNS(SVGNS, "feOffset");
		feOffsetElement.setAttribute("dx", "2");
		feOffsetElement.setAttribute("dy", "2");
		feOffsetElement.setAttribute("result", "offsetblur");
		filterElement.appendChild(feOffsetElement);

		var feMergeElement = document.createElementNS(SVGNS, "feMerge");
		filterElement.appendChild(feMergeElement);

		var feMergeNodeElement1 = document.createElementNS(SVGNS, "feMergeNode");
		feMergeElement.appendChild(feMergeNodeElement1);

		var feMergeNodeElement2 = document.createElementNS(SVGNS, "feMergeNode");
		feMergeNodeElement2.setAttribute("in", "SourceGraphic");
		feMergeElement.appendChild(feMergeNodeElement2);

		this.nodes = [];
		this.nodes.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
			return null;
		}
    }

	Canvas.prototype._onMouseDown = function(e){
		var targetId = e.target.getAttribute("id");
		draggingNode = _canvasInstance.nodes.getById(targetId);
		e.preventDefault();
	};

    return Canvas;
})();

wfjs1.CircleNode = (function () {
	var index = 0;

    function CircleNode(canvas, x, y, label, circle_options, text_options) {
		this.id = "wfjs_node_" + index;
		index++;
        this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;

		this.circle_options = {};
		for(var attr in CIRCLE_DEFAULT_OPTIONS){
			this.circle_options[attr] = CIRCLE_DEFAULT_OPTIONS[attr];
		}
		for(var attr in circle_options){
			this.circle_options[attr] = circle_options[attr];
		}

        this.text_options = text_options;
		this.flowlines = [];
    };

    CircleNode.prototype.show = function () {

		this.circleElement = document.createElementNS(SVGNS, "circle");
		this.circleElement.setAttribute("id", this.id);
		this.circleElement.setAttribute("style", "cursor: move;");
//		this.circleElement.setAttribute("filter", "url(#dropshadow1)");

		for(var attr in this.circle_options){
			this.circleElement.setAttribute(attr, this.circle_options[attr]);
		}

		this.circleElement.addEventListener("mousedown", this.canvas._onMouseDown, false);
		this.canvas.svgElement.appendChild(this.circleElement);

		var textElement = document.createElementNS(SVGNS, "text");

		textElement.textContent = this.label;

		for(var attr in TEXT_DEFAULT_OPTIONS){
			textElement.setAttribute(attr, TEXT_DEFAULT_OPTIONS[attr]);
		}

		if(this.text_options !=null && this.text_options !== undefined){
			for(var attr in this.text_options){
				textElement.setAttribute(attr, this.text_options[attr]);
			}
		}

		this.canvas.svgElement.appendChild(textElement);
		this.labelTextElement = textElement;
		this.canvas.nodes.push(this);

		this.move(this.x, this.y);

    }; // End of show()

    CircleNode.prototype.connectTo = function(node) {
		var flowLine = new wfjs1.FlowLine(this.canvas, this, node);
		this.flowlines.push(flowLine);
		node.flowlines.push(flowLine);

    }; // End of connectTo()

    CircleNode.prototype.move = function(x, y) {
		this.x = x;
		this.y = y;
		this.circleElement.setAttribute("cx", x);
		this.circleElement.setAttribute("cy", y);
		// label position
		var rect = this.labelTextElement.getBBox();
		this.labelTextElement.setAttribute("x", x - (rect.width/2));
		this.labelTextElement.setAttribute("y", y + 5); // TODO what is this magic number?
		for(var i = 0; i < this.flowlines.length; i++){
			this.flowlines[i].relocate();
		}

    }; // End of move()

    return CircleNode;
})(); // End of wfjs1.Node

wfjs1.DiamondNode = (function () {
    function DiamondNode(canvas, x, y, label){
		this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;

		this.rectElement = document.createElementNS(SVGNS, "rect");
		this.rectElement.setAttribute("transform", "rotate(45 " + x + " " + y + ")");

		for(var attr in DIAMOND_DEFAULT_OPTIONS){
			this.rectElement.setAttribute(attr, DIAMOND_DEFAULT_OPTIONS[attr]);
		}
		this.canvas.svgElement.appendChild(this.rectElement);

		// label
		this.textElement = document.createElementNS(SVGNS, "text");
		this.textElement.textContent = this.label;
		this.canvas.svgElement.appendChild(this.textElement);
//		this.canvas.nodes.push(this);

		this.move(x, y);
	};

    DiamondNode.prototype.move = function(x, y) {

		this.rectElement.setAttribute("x", x);
		this.rectElement.setAttribute("y", y);

		var rect = this.textElement.getBBox();
		this.textElement.setAttribute("x", x - (rect.width/2));
		this.textElement.setAttribute("y", y + 46); // TODO magic number

    }; // End of move()

    return DiamondNode;
})(); // End of wfjs1.DiamondNode

wfjs1.FlowLine = (function () {
	var HEAD_SHAPE_PATH = "l-5 10 l10 0 Z";

    function FlowLine(canvas, startNode, endNode){
		this.canvas = canvas;
		this.startNode = startNode;
		this.endNode = endNode;

		this.lineElement = document.createElementNS(SVGNS, "line");
		this.lineElement.setAttribute("style", "stroke: black;stroke-width:1;");
		this.canvas.svgElement.appendChild(this.lineElement);

		this.arrowPathElement = document.createElementNS(SVGNS, "path");
		this.arrowPathElement.setAttribute("fill", "black");
		this.arrowPathElement.setAttribute("stroke", "black");
		this.canvas.svgElement.appendChild(this.arrowPathElement);

		this.relocate();

	};

    FlowLine.prototype.relocate = function(){
		// The line end should not be the center of the target object, since it needs an arrow mark.
		var startRadian = Math.atan2(this.endNode.y - this.startNode.y, this.endNode.x - this.startNode.x);
		var startX = this.startNode.circle_options.r * Math.cos(startRadian) + this.startNode.x;
		var startY = this.startNode.circle_options.r * Math.sin(startRadian) + this.startNode.y;
		this.lineElement.setAttribute("x1", startX);
		this.lineElement.setAttribute("y1", startY);

		var endRadian = Math.atan2(this.startNode.y - this.endNode.y, this.startNode.x - this.endNode.x);
		var endX = this.endNode.circle_options.r * Math.cos(endRadian) + this.endNode.x;
		var endY = this.endNode.circle_options.r * Math.sin(endRadian) + this.endNode.y;
		this.lineElement.setAttribute("x2", endX);
		this.lineElement.setAttribute("y2", endY);

		var endDigree = (endRadian * 180 / Math.PI) - 90;
		this.arrowPathElement.setAttribute("d", "M" + endX + " " + endY + " " + HEAD_SHAPE_PATH);
		this.arrowPathElement.setAttribute("transform", "rotate(" + endDigree + " " + endX + " " + endY + ")");

    }; // End of relocate()

    return FlowLine;
})(); // End of wfjs1.FlowLine

return wfjs1;
})();

<commit_msg>layerX works?<commit_after>var wfjs = (function () {
var wfjs1 = {};

var SVGNS = "http://www.w3.org/2000/svg";

var TEXT_DEFAULT_OPTIONS = {
	fill : "black",
	"font-size" : "1em",
};

var CIRCLE_DEFAULT_OPTIONS = {
	r: 30,
	stroke: "blue",
	"stroke-width": "2",
	fill: "yellow",
	filter: "url(#dropshadow1)"
};

var DIAMOND_DEFAULT_OPTIONS = {
	stroke: "yellow",
	"stroke-width": "2",
	fill: "DarkSeaGreen",
	width : 60,
	height : 60,
	filter: "url(#dropshadow1)"
};

wfjs1.Canvas = (function () {
	var draggingNode = null;

	var _canvasInstance;
    function Canvas(containerId) {
		_canvasInstance = this;

		var _onMouseUp = function(e){
			if(draggingNode != null){
				draggingNode = null;
			}
		};

		var _onMouseMove = function(e){
			if(draggingNode != null ){
				var x, y;
				if(e.layerX==undefined){ // Firefox
					x = e.pageX-$(_canvasInstance.svgElement).offset().left;
					y = e.pageY-$(_canvasInstance.svgElement).offset().top;
				}else{ // Chrome
					x = e.layerX;
					y = e.layerY;
				}

				draggingNode.move(x, y);
//				draggingNode.move(e.layerX, e.layerY);
//				draggingNode.move(e.x, e.y);
//				console.debug(e.target);
//				console.debug("offsetX: " + e.offsetX + " e.x:" + e.x + " layerX:" + e.layerX);
				console.debug("tag:" + e.target.tagName + " screenY: " + e.screenY + " pageY: " + e.pageY + " clientY: " + e.clientY + " offsetY: " + e.offsetY + " e.y:" + e.y + " layerY:" + e.layerY);
			}
		};

        this.containerId = containerId;
		this.container = document.getElementById(containerId);

		var svgElement = document.createElementNS(SVGNS, "svg");
		svgElement.setAttribute("id", "wfjs_svg");
		svgElement.setAttribute("version", "1.1");
		svgElement.addEventListener("mouseup", _onMouseUp, false);
//		$(svgElement).on('mousemove', _onMouseMove);
		svgElement.addEventListener("mousemove", _onMouseMove, true);

		this.container.appendChild(svgElement);
		this.svgElement = svgElement;

		var defsElement = document.createElementNS(SVGNS, "defs");
		svgElement.appendChild(defsElement);

		var filterElement = document.createElementNS(SVGNS, "filter");
		filterElement.setAttribute("id", "dropshadow1");
		defsElement.appendChild(filterElement);

		var feGaussianBlurElement = document.createElementNS(SVGNS, "feGaussianBlur");
		feGaussianBlurElement.setAttribute("in", "SourceAlpha");
		feGaussianBlurElement.setAttribute("stdDeviation", "3");
		filterElement.appendChild(feGaussianBlurElement);

		var feOffsetElement = document.createElementNS(SVGNS, "feOffset");
		feOffsetElement.setAttribute("dx", "2");
		feOffsetElement.setAttribute("dy", "2");
		feOffsetElement.setAttribute("result", "offsetblur");
		filterElement.appendChild(feOffsetElement);

		var feMergeElement = document.createElementNS(SVGNS, "feMerge");
		filterElement.appendChild(feMergeElement);

		var feMergeNodeElement1 = document.createElementNS(SVGNS, "feMergeNode");
		feMergeElement.appendChild(feMergeNodeElement1);

		var feMergeNodeElement2 = document.createElementNS(SVGNS, "feMergeNode");
		feMergeNodeElement2.setAttribute("in", "SourceGraphic");
		feMergeElement.appendChild(feMergeNodeElement2);

		this.nodes = [];
		this.nodes.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
			return null;
		}
    }

	Canvas.prototype._onMouseDown = function(e){
		var targetId = e.target.getAttribute("id");
		draggingNode = _canvasInstance.nodes.getById(targetId);
		e.preventDefault();
	};

    return Canvas;
})();

wfjs1.CircleNode = (function () {
	var index = 0;

    function CircleNode(canvas, x, y, label, circle_options, text_options) {
		this.id = "wfjs_node_" + index;
		index++;
        this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;

		this.circle_options = {};
		for(var attr in CIRCLE_DEFAULT_OPTIONS){
			this.circle_options[attr] = CIRCLE_DEFAULT_OPTIONS[attr];
		}
		for(var attr in circle_options){
			this.circle_options[attr] = circle_options[attr];
		}

        this.text_options = text_options;
		this.flowlines = [];
    };

    CircleNode.prototype.show = function () {

		this.circleElement = document.createElementNS(SVGNS, "circle");
		this.circleElement.setAttribute("id", this.id);
		this.circleElement.setAttribute("style", "cursor: move;");
//		this.circleElement.setAttribute("filter", "url(#dropshadow1)");

		for(var attr in this.circle_options){
			this.circleElement.setAttribute(attr, this.circle_options[attr]);
		}

		this.circleElement.addEventListener("mousedown", this.canvas._onMouseDown, false);
		this.canvas.svgElement.appendChild(this.circleElement);

		var textElement = document.createElementNS(SVGNS, "text");

		textElement.textContent = this.label;

		for(var attr in TEXT_DEFAULT_OPTIONS){
			textElement.setAttribute(attr, TEXT_DEFAULT_OPTIONS[attr]);
		}

		if(this.text_options !=null && this.text_options !== undefined){
			for(var attr in this.text_options){
				textElement.setAttribute(attr, this.text_options[attr]);
			}
		}

		this.canvas.svgElement.appendChild(textElement);
		this.labelTextElement = textElement;
		this.canvas.nodes.push(this);

		this.move(this.x, this.y);

    }; // End of show()

    CircleNode.prototype.connectTo = function(node) {
		var flowLine = new wfjs1.FlowLine(this.canvas, this, node);
		this.flowlines.push(flowLine);
		node.flowlines.push(flowLine);

    }; // End of connectTo()

    CircleNode.prototype.move = function(x, y) {
		this.x = x;
		this.y = y;
		this.circleElement.setAttribute("cx", x);
		this.circleElement.setAttribute("cy", y);
		// label position
		var rect = this.labelTextElement.getBBox();
		this.labelTextElement.setAttribute("x", x - (rect.width/2));
		this.labelTextElement.setAttribute("y", y + 5); // TODO what is this magic number?
		for(var i = 0; i < this.flowlines.length; i++){
			this.flowlines[i].relocate();
		}

    }; // End of move()

    return CircleNode;
})(); // End of wfjs1.Node

wfjs1.DiamondNode = (function () {
    function DiamondNode(canvas, x, y, label){
		this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;

		this.rectElement = document.createElementNS(SVGNS, "rect");
		this.rectElement.setAttribute("transform", "rotate(45 " + x + " " + y + ")");

		for(var attr in DIAMOND_DEFAULT_OPTIONS){
			this.rectElement.setAttribute(attr, DIAMOND_DEFAULT_OPTIONS[attr]);
		}
		this.canvas.svgElement.appendChild(this.rectElement);

		// label
		this.textElement = document.createElementNS(SVGNS, "text");
		this.textElement.textContent = this.label;
		this.canvas.svgElement.appendChild(this.textElement);
//		this.canvas.nodes.push(this);

		this.move(x, y);
	};

    DiamondNode.prototype.move = function(x, y) {

		this.rectElement.setAttribute("x", x);
		this.rectElement.setAttribute("y", y);

		var rect = this.textElement.getBBox();
		this.textElement.setAttribute("x", x - (rect.width/2));
		this.textElement.setAttribute("y", y + 46); // TODO magic number

    }; // End of move()

    return DiamondNode;
})(); // End of wfjs1.DiamondNode

wfjs1.FlowLine = (function () {
	var HEAD_SHAPE_PATH = "l-5 10 l10 0 Z";

    function FlowLine(canvas, startNode, endNode){
		this.canvas = canvas;
		this.startNode = startNode;
		this.endNode = endNode;

		this.lineElement = document.createElementNS(SVGNS, "line");
		this.lineElement.setAttribute("style", "stroke: black;stroke-width:1;");
		this.canvas.svgElement.appendChild(this.lineElement);

		this.arrowPathElement = document.createElementNS(SVGNS, "path");
		this.arrowPathElement.setAttribute("fill", "black");
		this.arrowPathElement.setAttribute("stroke", "black");
		this.canvas.svgElement.appendChild(this.arrowPathElement);

		this.relocate();

	};

    FlowLine.prototype.relocate = function(){
		// The line end should not be the center of the target object, since it needs an arrow mark.
		var startRadian = Math.atan2(this.endNode.y - this.startNode.y, this.endNode.x - this.startNode.x);
		var startX = this.startNode.circle_options.r * Math.cos(startRadian) + this.startNode.x;
		var startY = this.startNode.circle_options.r * Math.sin(startRadian) + this.startNode.y;
		this.lineElement.setAttribute("x1", startX);
		this.lineElement.setAttribute("y1", startY);

		var endRadian = Math.atan2(this.startNode.y - this.endNode.y, this.startNode.x - this.endNode.x);
		var endX = this.endNode.circle_options.r * Math.cos(endRadian) + this.endNode.x;
		var endY = this.endNode.circle_options.r * Math.sin(endRadian) + this.endNode.y;
		this.lineElement.setAttribute("x2", endX);
		this.lineElement.setAttribute("y2", endY);

		var endDigree = (endRadian * 180 / Math.PI) - 90;
		this.arrowPathElement.setAttribute("d", "M" + endX + " " + endY + " " + HEAD_SHAPE_PATH);
		this.arrowPathElement.setAttribute("transform", "rotate(" + endDigree + " " + endX + " " + endY + ")");

    }; // End of relocate()

    return FlowLine;
})(); // End of wfjs1.FlowLine

return wfjs1;
})();

<|endoftext|>


<commit_before>fbf = {};

fbf.FRAMES_PER_SECOND = 25;
fbf.PLAYER_ID = "movie_player"

fbf.prevFrame = function() {
    // Based on YouTube enhancer userscript, http://userscripts.org/scripts/show/33042.
    player = document.getElementById(fbf.PLAYER_ID);
    player.pauseVideo();
    player.seekBy(-1 * (1/fbf.FRAMES_PER_SECOND));
}

fbf.nextFrame = function() {
    // Based on YouTube enhancer userscript, http://userscripts.org/scripts/show/33042.
    player = document.getElementById(fbf.PLAYER_ID);
    player.pauseVideo();
    player.seekBy(1 * (1/fbf.FRAMES_PER_SECOND));
}

fbf.injectControls = function() {
    var controls_html = " ";
    var control_bar = document.getElementsByClassName("html5-player-chrome")[0];

    var newButtons = document.createElement('div');
    newButtons.innerHTML = controls_html;
    newButtons.style.float = 'left';

    var child = document.getElementsByClassName('ytp-volume-hover-area')[0];

    control_bar.insertBefore(newButtons, child);

    var forward_button = document.getElementsByClassName("icon-to-end")[0];
    forward_button.addEventListener('click', function() {
        fbf.nextFrame();
    });

    var back_button = document.getElementsByClassName("icon-to-start")[0];
    back_button.addEventListener('click', function() {
        fbf.prevFrame();
    });
}

fbf.injectControls();<commit_msg>checks if html5 player is present<commit_after>fbf = {};

fbf.FRAMES_PER_SECOND = 25;
fbf.PLAYER_ID = "movie_player"

fbf.prevFrame = function() {
    // Based on YouTube enhancer userscript, http://userscripts.org/scripts/show/33042.
    player = document.getElementById(fbf.PLAYER_ID);
    player.pauseVideo();
    player.seekBy(-1 * (1/fbf.FRAMES_PER_SECOND));
}

fbf.nextFrame = function() {
    // Based on YouTube enhancer userscript, http://userscripts.org/scripts/show/33042.
    player = document.getElementById(fbf.PLAYER_ID);
    player.pauseVideo();
    player.seekBy(1 * (1/fbf.FRAMES_PER_SECOND));
}

fbf.injectControls = function() {
    var controls_html = " ";
    var control_bar = document.getElementsByClassName("html5-player-chrome")[0];

    var newButtons = document.createElement('div');
    newButtons.innerHTML = controls_html;
    newButtons.style.float = 'left';

    var child = document.getElementsByClassName('ytp-volume-hover-area')[0];

    control_bar.insertBefore(newButtons, child);

    var forward_button = document.getElementsByClassName("icon-to-end")[0];
    forward_button.addEventListener('click', function() {
        fbf.nextFrame();
    });

    var back_button = document.getElementsByClassName("icon-to-start")[0];
    back_button.addEventListener('click', function() {
        fbf.prevFrame();
    });
}

if (document.getElementsByClassName("html5-player-chrome")[0]) {
    fbf.injectControls();
};<|endoftext|>


<commit_before>angular.module('jupiterApp').controller('adminCRRapidEntryCtrl', ['$scope', '$http','$filter','$location','nodeAttributeDictionary','nodeRelationshipDictionary','nodeTypeDictionary', 'ngIdentity',
    function($scope,$http,$filter,$location,nodeAttributeDictionary,nodeRelationshipDictionary,nodeTypeDictionary,ngIdentity) {

    //.fromNewNode=false;
    //$scope.relCheckBox.toNewNode=false;

    //console.log(nodeRelationshipDictionary.RelationshipTypes);
    $scope.relValues=nodeRelationshipDictionary.RelationshipTypes;
    $scope.nodeTypeValues=nodeTypeDictionary.NodeTypes;

    $scope.identity = ngIdentity;
    $scope.colHeaders = [];
    $scope.nodetypeselect = 'DataElement';
    $scope.oneDataElement = {};
    $scope.showAddDataElement=false;

    $scope.isActive = function(route) {
        return route === $location.path();
    }

    function fetchDataElements(){
                $http.get('/api/node/dataElements/' + $scope.dataElementSelectedId).then(function(res) {
                $scope.dataElementsArray=res.data;

                //$scope.relarray=[];
                console.log(res.data);
                var i=1;
                $scope.dataElementsArray.forEach(function(d){
                    console.log(d);
                });
                $scope.colHeaders=Object.keys($scope.dataElementsArray[0]);
                if ($scope.dataElementsArray.length == 1 && $scope.dataElementsArray[0].id === '') {
                    $scope.dataElementsArray = [];
                }
                $scope.showAddDataElement=true;

            });
    }

    $scope.saveDataElementsServer=function(){
            var datapacket={};
            datapacket.dsetid=$scope.dataElementSelectedId;
            datapacket.dearray=$scope.dataElementsArray;
            $http.post('/api/node/save/saveDE/', datapacket).
                //$http({method: 'Post', url: '/api/mongo/postcr', data: {greeting: 'hi'}}).
              success(function(data, status, headers, config) {
                console.log(data);
              }).error(function(data, status) {
                console.log(data);
            });

    };

     $scope.saveDataElmRow =function(index){
            var datapacket={};
            datapacket.dsetid=$scope.dataElementSelectedId;
            datapacket.deObject=$scope.dataElementsArray[index];
            console.log(datapacket);
            $http.post('/api/node/save/saveDE/', datapacket).
                //$http({method: 'Post', url: '/api/mongo/postcr', data: {greeting: 'hi'}}).
              success(function(data, status, headers, config) {
                console.log(data);
                $scope.dataElementsArray[index].changed = false;
                alert('Data Element saved');
              }).error(function(data, status) {
                console.log(data);
                alert('Save failed');
            });

    };

    $scope.setDataElement=function($item){
        //console.log("start",$item.id, $scope.node);
        $scope.dataElementSelectedId=$item.id;
        $scope.dataElementSelectedName=$item.displayname;

        console.log($scope.dataElementSelectedId,$scope.dataElementSelectedName);
        fetchDataElements();

        //checkNewRel();
    };

    $scope.addDataElement = function() {
        $scope.oneDataElement["id"]=null;
        $scope.oneDataElement["cid"]=null;
        if (Object.keys($scope.oneDataElement).length > 0) {
            $scope.dataElementsArray.push($scope.oneDataElement);
            $scope.oneDataElement= {};
        }
        console.log($scope.dataElementsArray);
    }
    $scope.deleteDataElmRow = function(index) {

        $scope.dataElementsArray.splice(index,1);
        console.log($scope.dataElementsArray);

    }

    $scope.deFieldChanged = function(row,fldIdx)
    {
        //field=true;
     if (!isNaN(row)) {
        $scope.dataElementsArray[row]['changed'] = true;
     }
     else {
        $scope.oneDataElement['changed'] = true;

    }
  //    console.log("changed=true");
    }

}]);
<commit_msg>updated add new data element function to allow add if user actually entering something<commit_after>angular.module('jupiterApp').controller('adminCRRapidEntryCtrl', ['$scope', '$http','$filter','$location','nodeAttributeDictionary','nodeRelationshipDictionary','nodeTypeDictionary', 'ngIdentity',
    function($scope,$http,$filter,$location,nodeAttributeDictionary,nodeRelationshipDictionary,nodeTypeDictionary,ngIdentity) {

    //.fromNewNode=false;
    //$scope.relCheckBox.toNewNode=false;

    //console.log(nodeRelationshipDictionary.RelationshipTypes);
    $scope.relValues=nodeRelationshipDictionary.RelationshipTypes;
    $scope.nodeTypeValues=nodeTypeDictionary.NodeTypes;

    $scope.identity = ngIdentity;
    $scope.colHeaders = [];
    $scope.nodetypeselect = 'DataElement';
    $scope.oneDataElement = {};
    $scope.showAddDataElement=false;

    $scope.isActive = function(route) {
        return route === $location.path();
    }

    function fetchDataElements(){
                $http.get('/api/node/dataElements/' + $scope.dataElementSelectedId).then(function(res) {
                $scope.dataElementsArray=res.data;

                //$scope.relarray=[];
                console.log(res.data);
                var i=1;
                $scope.dataElementsArray.forEach(function(d){
                    console.log(d);
                });
                $scope.colHeaders=Object.keys($scope.dataElementsArray[0]);
                if ($scope.dataElementsArray.length == 1 && $scope.dataElementsArray[0].id === '') {
                    $scope.dataElementsArray = [];
                }
                $scope.showAddDataElement=true;

            });
    }

    $scope.saveDataElementsServer=function(){
            var datapacket={};
            datapacket.dsetid=$scope.dataElementSelectedId;
            datapacket.dearray=$scope.dataElementsArray;
            $http.post('/api/node/save/saveDE/', datapacket).
                //$http({method: 'Post', url: '/api/mongo/postcr', data: {greeting: 'hi'}}).
              success(function(data, status, headers, config) {
                console.log(data);
              }).error(function(data, status) {
                console.log(data);
            });

    };

     $scope.saveDataElmRow =function(index){
            var datapacket={};
            datapacket.dsetid=$scope.dataElementSelectedId;
            datapacket.deObject=$scope.dataElementsArray[index];
            console.log(datapacket);
            $http.post('/api/node/save/saveDE/', datapacket).
                //$http({method: 'Post', url: '/api/mongo/postcr', data: {greeting: 'hi'}}).
              success(function(data, status, headers, config) {
                console.log(data);
                $scope.dataElementsArray[index].changed = false;
                alert('Data Element saved');
              }).error(function(data, status) {
                console.log(data);
                alert('Save failed');
            });

    };

    $scope.setDataElement=function($item){
        //console.log("start",$item.id, $scope.node);
        $scope.dataElementSelectedId=$item.id;
        $scope.dataElementSelectedName=$item.displayname;

        console.log($scope.dataElementSelectedId,$scope.dataElementSelectedName);
        fetchDataElements();

        //checkNewRel();
    };

    $scope.addDataElement = function() {

        if (Object.keys($scope.oneDataElement).length > 0) {
            $scope.oneDataElement["id"]=null;
            $scope.oneDataElement["cid"]=null;
            $scope.oneDataElement['changed'] = true;
            $scope.dataElementsArray.push($scope.oneDataElement);
            $scope.oneDataElement= {};
        }
        console.log($scope.dataElementsArray);
    }
    $scope.deleteDataElmRow = function(index) {

        $scope.dataElementsArray.splice(index,1);
        console.log($scope.dataElementsArray);

    }

    $scope.deFieldChanged = function(row,fldIdx)
    {
        //field=true;
     if (!isNaN(row)) {
        $scope.dataElementsArray[row]['changed'] = true;
     }
     else {
        $scope.oneDataElement['changed'] = true;

    }
  //    console.log("changed=true");
    }

}]);
<|endoftext|>


<commit_before>import { VACCINE_PRESCRIPTION_ACTIONS } from '../../actions/Entities';
import { UIDatabase } from '../../database';

const initialState = () => ({
  creating: undefined,
  selectedVaccines: [],
  selectedBatches: [],
  vaccines: UIDatabase.objects('Vaccine'),
});

export const VaccinePrescriptionReducer = (state = initialState(), action) => {
  const { type } = action;

  switch (type) {
    case 'Navigation/BACK': {
      // reset if heading back
      return initialState();
    }

    case VACCINE_PRESCRIPTION_ACTIONS.CREATE: {
      const { payload } = action;
      const { prescription } = payload;

      return { ...state, creating: prescription };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SAVE: {
      const { payload } = action;
      const { prescription } = payload;

      return { ...state, creating: prescription.toJSON() };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SELECT_VACCINE: {
      const { payload } = action;
      const { vaccine } = payload;

      return { ...state, selectedVaccines: [vaccine] };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SELECT_BATCH: {
      const { payload } = action;
      const { itemBatch } = payload;

      return { ...state, selectedBatches: [itemBatch] };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.RESET: {
      return initialState();
    }

    case VACCINE_PRESCRIPTION_ACTIONS.UPDATE: {
      const { creating: oldPrescription } = state;
      const { payload } = action;
      const { field, value } = payload;

      const newPrescription = { ...oldPrescription, [field]: value };

      return { ...state, creating: newPrescription };
    }
    default: {
      return state;
    }
  }
};
<commit_msg>reset batch selection on change<commit_after>import { VACCINE_PRESCRIPTION_ACTIONS } from '../../actions/Entities';
import { UIDatabase } from '../../database';

const initialState = () => ({
  creating: undefined,
  selectedVaccines: [],
  selectedBatches: [],
  vaccines: UIDatabase.objects('Vaccine'),
});

export const VaccinePrescriptionReducer = (state = initialState(), action) => {
  const { type } = action;

  switch (type) {
    case 'Navigation/BACK': {
      // reset if heading back
      return initialState();
    }

    case VACCINE_PRESCRIPTION_ACTIONS.CREATE: {
      const { payload } = action;
      const { prescription } = payload;

      return { ...state, creating: prescription };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SAVE: {
      const { payload } = action;
      const { prescription } = payload;

      return { ...state, creating: prescription.toJSON() };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SELECT_VACCINE: {
      const { payload } = action;
      const { vaccine } = payload;

      return { ...state, selectedVaccines: [vaccine], selectedBatches: [] };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.SELECT_BATCH: {
      const { payload } = action;
      const { itemBatch } = payload;

      return { ...state, selectedBatches: [itemBatch] };
    }

    case VACCINE_PRESCRIPTION_ACTIONS.RESET: {
      return initialState();
    }

    case VACCINE_PRESCRIPTION_ACTIONS.UPDATE: {
      const { creating: oldPrescription } = state;
      const { payload } = action;
      const { field, value } = payload;

      const newPrescription = { ...oldPrescription, [field]: value };

      return { ...state, creating: newPrescription };
    }
    default: {
      return state;
    }
  }
};
<|endoftext|>


<commit_before>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function() {

    'use strict';

    /**
     * @ngdoc service
     * @name requisition-view.RequisitionWatcher
     *
     * @description
     * Provides auto-save feature to the requisition. Notifies when changes are being made to the
     * watched requisition - this can be avoided by silencing the watcher.
     */
    angular
        .module('requisition-view')
        .factory('RequisitionWatcher', factory);

    factory.$inject = ['$timeout'];

    function factory($timeout) {

        return RequisitionWatcher;

        /**
         * @ngdoc method
         * @methodOf requisition-view.RequisitionWatcher
         * @name RequisitionWatcher
         *
         * @description
         * Creates requisition watcher for changes in requisition line items and comments.
         *
         * @param  {Scope}              scope       scope that requisition is in
         * @param  {Object}             requisition requisition to set watcher on
         * @return {RequisitionWatcher}             watcher object
         */
        function RequisitionWatcher(scope, requisition, storage) {
            var watcher = this;

            watcher.enabled = true;

            watcher.disableWatcher = disableWatcher;
            watcher.enableWatcher = enableWatcher;

            addWatcher(scope, requisition, 'requisitionLineItems', watcher, storage);
            addWatcher(scope, requisition, 'draftStatusMessage', watcher, storage);

            function enableWatcher() {
                watcher.enabled = true;
            }

            function disableWatcher() {
                watcher.enabled = false;
            }
        }

        function addWatcher(scope, requisition, valueToWatch, watcher, storage) {
            scope.$watch(function() {
                return requisition[valueToWatch];
            }, function(oldValue, newValue) {
                if (oldValue !== newValue && watcher.enabled) {
                    $timeout.cancel(watcher.syncTimeout);
                    watcher.syncTimeout = $timeout(function() {
                        requisition.$modified = true;
                        storage.put(requisition);
                        watcher.syncTimeout = undefined;
                    }, 500);
                }
            }, true);
        }
    }

})();
<commit_msg>OLMIS-5724: Refactored RequisitionWatcher so its methods are now defined with prototype<commit_after>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function() {

    'use strict';

    /**
     * @ngdoc service
     * @name requisition-view.RequisitionWatcher
     *
     * @description
     * Provides auto-save feature to the requisition. Notifies when changes are being made to the
     * watched requisition - this can be avoided by silencing the watcher.
     */
    angular
        .module('requisition-view')
        .factory('RequisitionWatcher', factory);

    factory.$inject = ['$timeout'];

    function factory($timeout) {

        RequisitionWatcher.prototype.disableWatcher = disableWatcher;
        RequisitionWatcher.prototype.enableWatcher = enableWatcher;

        return RequisitionWatcher;

        /**
         * @ngdoc method
         * @methodOf requisition-view.RequisitionWatcher
         * @name RequisitionWatcher
         *
         * @description
         * Creates requisition watcher for changes in requisition line items and comments.
         *
         * @param  {Scope}              scope       scope that requisition is in
         * @param  {Object}             requisition requisition to set watcher on
         * @return {RequisitionWatcher}             watcher object
         */
        function RequisitionWatcher(scope, requisition, storage) {
            this.enabled = true;

            addWatcher(scope, requisition, 'requisitionLineItems', this, storage);
            addWatcher(scope, requisition, 'draftStatusMessage', this, storage);
        }

        function enableWatcher() {
            this.enabled = true;
        }

        function disableWatcher() {
            this.enabled = false;
        }

        function addWatcher(scope, requisition, valueToWatch, watcher, storage) {
            scope.$watch(function() {
                return requisition[valueToWatch];
            }, function(oldValue, newValue) {
                if (oldValue !== newValue && watcher.enabled) {
                    $timeout.cancel(watcher.syncTimeout);
                    watcher.syncTimeout = $timeout(function() {
                        requisition.$modified = true;
                        storage.put(requisition);
                        watcher.syncTimeout = undefined;
                    }, 500);
                }
            }, true);
        }
    }

})();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { browserHistory } from 'react-router';

class SuccessPage extends Component {
  constructor(props) {
    super(props);
    this.state = { };
  }

  render() {
    let { ticket, event } = this.props;
    return (

Finished!

You just registered your {ticket.type} ticket for {event.name}.

              <button className="btn-large" onClick={() => browserHistory.push(`/event/${ticket.eventId}/ticket/${ticket._id}`)}>View Ticket</button>

    );
  }
}

export default SuccessPage;
<commit_msg>fixed eventId<commit_after>import React, { Component } from 'react';
import { browserHistory } from 'react-router';

class SuccessPage extends Component {
  constructor(props) {
    super(props);
    this.state = { };
  }

  render() {
    let { ticket, event } = this.props;
    return (

Finished!

You just registered your {ticket.type} ticket for {event.name}.

              <button className="btn-large" onClick={() => browserHistory.push(`/event/${ticket.eventId._id}/ticket/${ticket._id}`)}>View Ticket</button>

    );
  }
}

export default SuccessPage;
<|endoftext|>


<commit_before>/*global describe,it,takeScreenshot,browser,expect*/

describe("sap.m.SegmentedButton", function() {
	"use strict";

	browser.testrunner.currentSuite.meta.controlName = 'sap.m.SegmentedButton';

	it("should render SegmentedButton", function() {
		expect(takeScreenshot()).toLookAs("SegmentedButton_initial");
	}, 6000);

});<commit_msg>[INTERNAL] sap.m.SegmentedButton: Extending test timeout<commit_after>/*global describe,it,takeScreenshot,browser,expect*/

describe("sap.m.SegmentedButton", function() {
	"use strict";

	browser.testrunner.currentSuite.meta.controlName = 'sap.m.SegmentedButton';

	it("should render SegmentedButton", function() {
		expect(takeScreenshot()).toLookAs("SegmentedButton_initial");
	}, 12000);

});<|endoftext|>


<commit_before>var util = require('util');

module.exports = function(ctx, cb) {
  console.log(util.inspect(ctx.body, {depth:null}));
  cb();
};<commit_msg>using import and arrow functions<commit_after>"use latest";
import util from 'util';

module.exports = (ctx, cb) => {
  // console.log(util.inspect(ctx.body, {depth:null}));
  console.log(util.inspect(ctx.body.issue.url));
  cb();
};<|endoftext|>


<commit_before>var torrents = require('torrent-stream')
var request = require('request')
var duplex = require('duplexify')
var ytdl = require('ytdl-core')
var events = require('events')
var path = require('path')
var fs = require('fs')
var vtt = require('srt-to-vtt')
var concat = require('concat-stream')

var noop = function () {}

module.exports = function () {
  var that = new events.EventEmitter()

  that.entries = []

  var onmagnet = function (link, cb) {
    console.log('torrent ' + link)

    var engine = torrents(link)

    engine.swarm.add('127.0.0.1:51413') // me!

    engine.on('ready', function () {
      console.log('torrent ready')

      engine.files.forEach(function (f) {
        f.downloadSpeed = engine.swarm.downloadSpeed
        if (/\.(mp4|mkv|mp3)$/i.test(f.name)) {
          f.select()
          f.id = that.entries.push(f) - 1
        }
      })

      setInterval(function () {
        console.log(engine.swarm.downloadSpeed() + ' (' + engine.swarm.wires.length + ')')
      }, 1000)

      that.emit('update')
      cb()
    })
  }

  var ontorrent = function (link, cb) {
    fs.readFile(link, function (err, buf) {
      if (err) return cb(err)
      onmagnet(buf, cb)
    })
  }

  var onyoutube = function (link, cb) {
    var file = {}
    var url = link.split(':')[1]
    url = 'https:' + url

    getYoutubeData(function (err, data) {
      if (err) return cb(err)
      var fmt = data.fmt
      var info = data.info
      request({method: 'HEAD', url: fmt.url}, function (err, resp, body) {
        if (err) return cb(err)
        var len = resp.headers['content-length']
        if (!len) return cb(new Error('no content-length on response'))
        file.length = +len
        file.name = info.title

        file.createReadStream = function (opts) {
          if (!opts) opts = {}
          // fetch this for every range request
          // TODO try and avoid doing this call twice the first time
          getYoutubeData(function (err, data) {
            if (err) return cb(err)
            var vidUrl = data.fmt.url
            if (opts.start || opts.end) vidUrl += '&range=' + ([opts.start || 0, opts.end || len].join('-'))
            stream.setReadable(request(vidUrl))
          })

          var stream = duplex()
          return stream
        }
        file.id = that.entries.push(file) - 1
        that.emit('update')
        cb()
      })
    })

    function getYoutubeData (cb) {
      ytdl.getInfo(url, function (err, info) {
        if (err) return cb(err)

        var vidFmt
        var formats = info.formats

        formats.sort(function sort (a, b) {
          return +a.itag - +b.itag
        })

        var vidFmt
        formats.forEach(function (fmt) {
          // prefer webm
          if (fmt.itag === '46') return vidFmt = fmt
          if (fmt.itag === '45') return vidFmt = fmt
          if (fmt.itag === '44') return vidFmt = fmt
          if (fmt.itag === '43') return vidFmt = fmt

          // otherwise h264
          if (fmt.itag === '38') return vidFmt = fmt
          if (fmt.itag === '37') return vidFmt = fmt
          if (fmt.itag === '22') return vidFmt = fmt
          if (fmt.itag === '18') return vidFmt = fmt
        })

        if (!vidFmt) return cb (new Error('No suitable video format found'))

        cb(null, {info: info, fmt: vidFmt})
      })
    }
  }

  var onfile = function (link, cb) {
    var file = {}

    fs.stat(link, function (err, st) {
      if (err) return cb(err)

      file.length = st.size
      file.name = path.basename(link)
      file.createReadStream = function (opts) {
        return fs.createReadStream(link, opts)
      }

      file.id = that.entries.push(file) - 1

      var ondone = function () {
        that.emit('update')
        cb()
      }
      var basename = link.substr(0, link.lastIndexOf('.'))
      var extensions = ['srt', 'vtt']
      var next = function () {
        var ext = extensions.shift()
        if (!ext) return ondone()

        fs.exists(basename + '.' + ext, function(exists) {
          if (!exists) return next()
          fs.createReadStream(basename + '.' + ext).pipe(vtt()).pipe(concat(function(data) {
            file.subtitles = data
            ondone()
          }))
        })
      }
      next()
    })
  }

  var onhttplink = function (link, cb) {
    var file = {}

    file.name = link.lastIndexOf('/') > -1 ? link.split('/').pop() : link

    file.createReadStream = function (opts) {
      if (!opts) opts = {}

      if (opts && (opts.start || opts.end)) {
        var rs = 'bytes=' + (opts.start || 0) + '-' + (opts.end || file.length || '')
        return request(link, {headers: {Range: rs}})
      }

      return request(link)
    }

    // first, get the head for the content length.
    // IMPORTANT: servers without HEAD will not work.
    request.head(link, function (err, response) {
      if (err) return cb(err)
      if (!/2\d\d/.test(response.statusCode)) return cb(new Error('request failed'))

      file.length = Number(response.headers['content-length'])
      file.id = that.entries.push(file) - 1
      that.emit('update')
      cb()
    })
  }

  var onipfslink = function (link, cb) {
    var local = 'localhost:8080' // todo: make this configurable
    var gateway = 'gateway.ipfs.io'
    var file = {}

    // first, try the local http gateway
    console.log('trying local ipfs gateway at ' + local)
    var u = 'http://' + local + link
    onhttplink(u, function (err) {
      if (!err) return cb() // done.

      // error? ok try fuse... maybe the gateway's broken.
      console.log('trying mounted ipfs fs (just in case)')
      onfile(link, function (err) {
        if (!err) return cb() // done.

        // worst case, try global ipfs gateway.
        console.log('trying ipfs global gateway')
        var u = 'http://' + gateway + link
        onhttplink(u, cb)
      })
    })
  }

  that.selected = null

  that.deselect = function () {
    that.selected = null
    that.emit('deselect')
  }

  that.selectNext = function () {
    if (!that.entries.length) return null
    if (!that.selected) return that.select(0)
    if (that.selected.id === that.entries.length - 1) return null
    return that.select(that.selected.id + 1)
  }

  that.select = function (id) {
    that.selected = that.get(id)
    that.emit('select')
    return that.selected
  }

  that.get = function (id) {
    return that.entries[id]
  }

  that.add = function (link, cb) {
    if (!cb) cb = noop
    if (/magnet:/.test(link)) return onmagnet(link, cb)
    if (/\.torrent$/i.test(link)) return ontorrent(link, cb)
    if (/youtube\.com\/watch/i.test(link)) return onyoutube(link, cb)
    if (/^\/(ipfs|ipns)\//i.test(link)) return onipfslink(link, cb)
    if (/^\/https?:\/\//i.test(link)) return onhttplink(link, cb)
    onfile(link, cb)
  }

  return that
}<commit_msg>strip playback protocol<commit_after>var torrents = require('torrent-stream')
var request = require('request')
var duplex = require('duplexify')
var ytdl = require('ytdl-core')
var events = require('events')
var path = require('path')
var fs = require('fs')
var vtt = require('srt-to-vtt')
var concat = require('concat-stream')

var noop = function () {}

module.exports = function () {
  var that = new events.EventEmitter()

  that.entries = []

  var onmagnet = function (link, cb) {
    console.log('torrent ' + link)

    var engine = torrents(link)

    engine.swarm.add('127.0.0.1:51413') // me!

    engine.on('ready', function () {
      console.log('torrent ready')

      engine.files.forEach(function (f) {
        f.downloadSpeed = engine.swarm.downloadSpeed
        if (/\.(mp4|mkv|mp3)$/i.test(f.name)) {
          f.select()
          f.id = that.entries.push(f) - 1
        }
      })

      setInterval(function () {
        console.log(engine.swarm.downloadSpeed() + ' (' + engine.swarm.wires.length + ')')
      }, 1000)

      that.emit('update')
      cb()
    })
  }

  var ontorrent = function (link, cb) {
    fs.readFile(link, function (err, buf) {
      if (err) return cb(err)
      onmagnet(buf, cb)
    })
  }

  var onyoutube = function (link, cb) {
    var file = {}
    var url = /https?:/.test(link) ? link : 'https:' + link

    getYoutubeData(function (err, data) {
      if (err) return cb(err)
      var fmt = data.fmt
      var info = data.info
      request({method: 'HEAD', url: fmt.url}, function (err, resp, body) {
        if (err) return cb(err)
        var len = resp.headers['content-length']
        if (!len) return cb(new Error('no content-length on response'))
        file.length = +len
        file.name = info.title

        file.createReadStream = function (opts) {
          if (!opts) opts = {}
          // fetch this for every range request
          // TODO try and avoid doing this call twice the first time
          getYoutubeData(function (err, data) {
            if (err) return cb(err)
            var vidUrl = data.fmt.url
            if (opts.start || opts.end) vidUrl += '&range=' + ([opts.start || 0, opts.end || len].join('-'))
            stream.setReadable(request(vidUrl))
          })

          var stream = duplex()
          return stream
        }
        file.id = that.entries.push(file) - 1
        that.emit('update')
        cb()
      })
    })

    function getYoutubeData (cb) {
      ytdl.getInfo(url, function (err, info) {
        if (err) return cb(err)

        var vidFmt
        var formats = info.formats

        formats.sort(function sort (a, b) {
          return +a.itag - +b.itag
        })

        var vidFmt
        formats.forEach(function (fmt) {
          // prefer webm
          if (fmt.itag === '46') return vidFmt = fmt
          if (fmt.itag === '45') return vidFmt = fmt
          if (fmt.itag === '44') return vidFmt = fmt
          if (fmt.itag === '43') return vidFmt = fmt

          // otherwise h264
          if (fmt.itag === '38') return vidFmt = fmt
          if (fmt.itag === '37') return vidFmt = fmt
          if (fmt.itag === '22') return vidFmt = fmt
          if (fmt.itag === '18') return vidFmt = fmt
        })

        if (!vidFmt) return cb (new Error('No suitable video format found'))

        cb(null, {info: info, fmt: vidFmt})
      })
    }
  }

  var onfile = function (link, cb) {
    var file = {}

    fs.stat(link, function (err, st) {
      if (err) return cb(err)

      file.length = st.size
      file.name = path.basename(link)
      file.createReadStream = function (opts) {
        return fs.createReadStream(link, opts)
      }

      file.id = that.entries.push(file) - 1

      var ondone = function () {
        that.emit('update')
        cb()
      }
      var basename = link.substr(0, link.lastIndexOf('.'))
      var extensions = ['srt', 'vtt']
      var next = function () {
        var ext = extensions.shift()
        if (!ext) return ondone()

        fs.exists(basename + '.' + ext, function(exists) {
          if (!exists) return next()
          fs.createReadStream(basename + '.' + ext).pipe(vtt()).pipe(concat(function(data) {
            file.subtitles = data
            ondone()
          }))
        })
      }
      next()
    })
  }

  var onhttplink = function (link, cb) {
    var file = {}

    file.name = link.lastIndexOf('/') > -1 ? link.split('/').pop() : link

    file.createReadStream = function (opts) {
      if (!opts) opts = {}

      if (opts && (opts.start || opts.end)) {
        var rs = 'bytes=' + (opts.start || 0) + '-' + (opts.end || file.length || '')
        return request(link, {headers: {Range: rs}})
      }

      return request(link)
    }

    // first, get the head for the content length.
    // IMPORTANT: servers without HEAD will not work.
    request.head(link, function (err, response) {
      if (err) return cb(err)
      if (!/2\d\d/.test(response.statusCode)) return cb(new Error('request failed'))

      file.length = Number(response.headers['content-length'])
      file.id = that.entries.push(file) - 1
      that.emit('update')
      cb()
    })
  }

  var onipfslink = function (link, cb) {
    var local = 'localhost:8080' // todo: make this configurable
    var gateway = 'gateway.ipfs.io'
    var file = {}

    // first, try the local http gateway
    console.log('trying local ipfs gateway at ' + local)
    var u = 'http://' + local + link
    onhttplink(u, function (err) {
      if (!err) return cb() // done.

      // error? ok try fuse... maybe the gateway's broken.
      console.log('trying mounted ipfs fs (just in case)')
      onfile(link, function (err) {
        if (!err) return cb() // done.

        // worst case, try global ipfs gateway.
        console.log('trying ipfs global gateway')
        var u = 'http://' + gateway + link
        onhttplink(u, cb)
      })
    })
  }

  that.selected = null

  that.deselect = function () {
    that.selected = null
    that.emit('deselect')
  }

  that.selectNext = function () {
    if (!that.entries.length) return null
    if (!that.selected) return that.select(0)
    if (that.selected.id === that.entries.length - 1) return null
    return that.select(that.selected.id + 1)
  }

  that.select = function (id) {
    that.selected = that.get(id)
    that.emit('select')
    return that.selected
  }

  that.get = function (id) {
    return that.entries[id]
  }

  that.add = function (link, cb) {
    link = link.replace('playback://').replace('playback:', '') // strip playback protocol
    if (!cb) cb = noop
    if (/magnet:/.test(link)) return onmagnet(link, cb)
    if (/\.torrent$/i.test(link)) return ontorrent(link, cb)
    if (/youtube\.com\/watch/i.test(link)) return onyoutube(link, cb)
    if (/^\/(ipfs|ipns)\//i.test(link)) return onipfslink(link, cb)
    if (/^\/https?:\/\//i.test(link)) return onhttplink(link, cb)
    onfile(link, cb)
  }

  return that
}<|endoftext|>


<commit_before>var torrents = require('torrent-stream')
var request = require('request')
var duplex = require('duplexify')
var ytdl = require('ytdl-core')
var events = require('events')
var path = require('path')
var httpStream = require('http-client-stream')
var fs = require('fs')
var vtt = require('srt-to-vtt')
var concat = require('concat-stream')

var noop = function () {}

module.exports = function () {
  var that = new events.EventEmitter()

  that.entries = []

  var onmagnet = function (link, cb) {
    console.log('torrent ' + link)

    var engine = torrents(link)

    engine.swarm.add('127.0.0.1:51413') // me!

    engine.on('ready', function () {
      console.log('torrent ready')

      engine.files.forEach(function (f) {
        f.downloadSpeed = engine.swarm.downloadSpeed
        if (/\.(mp4|mkv|mp3)$/i.test(f.name)) {
          f.select()
          f.id = that.entries.push(f) - 1
        }
      })

      setInterval(function () {
        console.log(engine.swarm.downloadSpeed() + ' (' + engine.swarm.wires.length + ')')
      }, 1000)

      that.emit('update')
      cb()
    })
  }

  var ontorrent = function (link, cb) {
    fs.readFile(link, function (err, buf) {
      if (err) return cb(err)
      onmagnet(buf, cb)
    })
  }

  var onyoutube = function (link, cb) {
    var file = {}
    var url = link.split(':')[1]
    url = 'https:' + url

    getYoutubeData(function (err, data) {
      if (err) return cb(err)
      var fmt = data.fmt
      var info = data.info
      request({method: 'HEAD', url: fmt.url}, function (err, resp, body) {
        if (err) return cb(err)
        var len = resp.headers['content-length']
        if (!len) return cb(new Error('no content-length on response'))
        file.length = +len
        file.name = info.title

        file.createReadStream = function (opts) {
          // fetch this for every range request
          // TODO try and avoid doing this call twice the first time
          getYoutubeData(function (err, data) {
            if (err) return cb(err)
            var vidUrl = data.fmt.url
            if (opts.start || opts.end) vidUrl += '&range=' + ([opts.start || 0, opts.end || len].join('-'))
            stream.setReadable(request(vidUrl))
          })

          var stream = duplex()
          return stream
        }
        file.id = that.entries.push(file) - 1
        that.emit('update')
        cb()
      })
    })

    function getYoutubeData(cb) {
      ytdl.getInfo(url, function (err, info) {
        if (err) return cb(err)

        var vidFmt
        var formats = info.formats

        formats.sort(function sort (a, b) {
          return +a.itag - +b.itag
        })

        var vidFmt
        formats.forEach(function (fmt) {
          // prefer webm
          if (fmt.itag === '46') return vidFmt = fmt
          if (fmt.itag === '45') return vidFmt = fmt
          if (fmt.itag === '44') return vidFmt = fmt
          if (fmt.itag === '43') return vidFmt = fmt

          // otherwise h264
          if (fmt.itag === '38') return vidFmt = fmt
          if (fmt.itag === '37') return vidFmt = fmt
          if (fmt.itag === '22') return vidFmt = fmt
          if (fmt.itag === '18') return vidFmt = fmt
        })

        if (!vidFmt) return cb (new Error('No suitable video format found'))

        cb(null, {info: info, fmt: vidFmt})
      })
    }
  }

  var onfile = function (link, cb) {
    var file = {}

    fs.stat(link, function (err, st) {
      if (err) return cb(err)

      file.length = st.size
      file.name = path.basename(link)
      file.createReadStream = function (opts) {
        return fs.createReadStream(link, opts)
      }

      file.id = that.entries.push(file) - 1

      var ondone = function () {
        that.emit('update')
        cb()
      }
      var basename = link.substr(0, link.lastIndexOf('.'))
      var extensions = ['srt', 'vtt']
      var next = function () {
        var ext = extensions.shift()
        if (!ext) return ondone()

        fs.exists(basename + '.' + ext, function(exists) {
          if (!exists) return next()
          fs.createReadStream(basename + '.' + ext).pipe(vtt()).pipe(concat(function(data) {
            file.subtitles = data
            ondone()
          }))
        })
      }
      next()
    })
  }

  var onhttplink = function (link, cb) {
    var file = httpStream(link)

    // call the http-stream's createStream with given range.
    file.createReadStream = function(range) {
      var rangestr = "bytes=" + range.start + '-' + range.end
      var opts = {"headers": {"Range": rangestr} }

      var stream = file.createStream(opts)
      stream.end()
      return stream
    }

    // first, get the head for the content length.
    // IMPORTANT: servers without HEAD will not work.
    var head = file.createStream({method: 'HEAD'})
    head.on('response', function() {
      if (!/2\d\d/.test(head.res.statusCode))
        cb(new Error("request failed"))

      // get the file length
      file.length = head.res.headers['content-length']
      console.log('found stream of length ' + file.length)

      // ok it worked. add the file.
      file.id = that.entries.push(file) - 1
      that.emit('update')
      cb()
    })

    head.on('error', function(err) {
      console.log(err)
      cb(err)
    })

    head.end()
  }

  that.selected = null

  that.deselect = function () {
    that.selected = null
    that.emit('deselect')
  }

  that.selectNext = function () {
    if (!that.entries.length) return null
    if (!that.selected) return that.select(0)
    if (that.selected.id === that.entries.length - 1) return null
    return that.select(that.selected.id + 1)
  }

  that.select = function (id) {
    that.selected = that.get(id)
    that.emit('select')
    return that.selected
  }

  that.get = function (id) {
    return that.entries[id]
  }

  that.add = function (link, cb) {
    if (!cb) cb = noop
    if (/magnet:/.test(link)) return onmagnet(link, cb)
    if (/\.torrent$/i.test(link)) return ontorrent(link, cb)
    if (/youtube\.com\/watch/i.test(link)) return onyoutube(link, cb)
    if (/^\/https?:\/\//i.test(link)) return onhttplink(link, cb)
    onfile(link, cb)
  }

  return that
}<commit_msg>ipfs path resolution<commit_after>var torrents = require('torrent-stream')
var request = require('request')
var duplex = require('duplexify')
var ytdl = require('ytdl-core')
var events = require('events')
var path = require('path')
var httpStream = require('http-client-stream')
var fs = require('fs')
var vtt = require('srt-to-vtt')
var concat = require('concat-stream')

var noop = function () {}

module.exports = function () {
  var that = new events.EventEmitter()

  that.entries = []

  var onmagnet = function (link, cb) {
    console.log('torrent ' + link)

    var engine = torrents(link)

    engine.swarm.add('127.0.0.1:51413') // me!

    engine.on('ready', function () {
      console.log('torrent ready')

      engine.files.forEach(function (f) {
        f.downloadSpeed = engine.swarm.downloadSpeed
        if (/\.(mp4|mkv|mp3)$/i.test(f.name)) {
          f.select()
          f.id = that.entries.push(f) - 1
        }
      })

      setInterval(function () {
        console.log(engine.swarm.downloadSpeed() + ' (' + engine.swarm.wires.length + ')')
      }, 1000)

      that.emit('update')
      cb()
    })
  }

  var ontorrent = function (link, cb) {
    fs.readFile(link, function (err, buf) {
      if (err) return cb(err)
      onmagnet(buf, cb)
    })
  }

  var onyoutube = function (link, cb) {
    var file = {}
    var url = link.split(':')[1]
    url = 'https:' + url

    getYoutubeData(function (err, data) {
      if (err) return cb(err)
      var fmt = data.fmt
      var info = data.info
      request({method: 'HEAD', url: fmt.url}, function (err, resp, body) {
        if (err) return cb(err)
        var len = resp.headers['content-length']
        if (!len) return cb(new Error('no content-length on response'))
        file.length = +len
        file.name = info.title

        file.createReadStream = function (opts) {
          // fetch this for every range request
          // TODO try and avoid doing this call twice the first time
          getYoutubeData(function (err, data) {
            if (err) return cb(err)
            var vidUrl = data.fmt.url
            if (opts.start || opts.end) vidUrl += '&range=' + ([opts.start || 0, opts.end || len].join('-'))
            stream.setReadable(request(vidUrl))
          })

          var stream = duplex()
          return stream
        }
        file.id = that.entries.push(file) - 1
        that.emit('update')
        cb()
      })
    })

    function getYoutubeData(cb) {
      ytdl.getInfo(url, function (err, info) {
        if (err) return cb(err)

        var vidFmt
        var formats = info.formats

        formats.sort(function sort (a, b) {
          return +a.itag - +b.itag
        })

        var vidFmt
        formats.forEach(function (fmt) {
          // prefer webm
          if (fmt.itag === '46') return vidFmt = fmt
          if (fmt.itag === '45') return vidFmt = fmt
          if (fmt.itag === '44') return vidFmt = fmt
          if (fmt.itag === '43') return vidFmt = fmt

          // otherwise h264
          if (fmt.itag === '38') return vidFmt = fmt
          if (fmt.itag === '37') return vidFmt = fmt
          if (fmt.itag === '22') return vidFmt = fmt
          if (fmt.itag === '18') return vidFmt = fmt
        })

        if (!vidFmt) return cb (new Error('No suitable video format found'))

        cb(null, {info: info, fmt: vidFmt})
      })
    }
  }

  var onfile = function (link, cb) {
    var file = {}

    fs.stat(link, function (err, st) {
      if (err) return cb(err)

      file.length = st.size
      file.name = path.basename(link)
      file.createReadStream = function (opts) {
        return fs.createReadStream(link, opts)
      }

      file.id = that.entries.push(file) - 1

      var ondone = function () {
        that.emit('update')
        cb()
      }
      var basename = link.substr(0, link.lastIndexOf('.'))
      var extensions = ['srt', 'vtt']
      var next = function () {
        var ext = extensions.shift()
        if (!ext) return ondone()

        fs.exists(basename + '.' + ext, function(exists) {
          if (!exists) return next()
          fs.createReadStream(basename + '.' + ext).pipe(vtt()).pipe(concat(function(data) {
            file.subtitles = data
            ondone()
          }))
        })
      }
      next()
    })
  }

  var onhttplink = function (link, cb) {
    var file = httpStream(link)

    // call the http-stream's createStream with given range.
    file.createReadStream = function(range) {
      var rangestr = "bytes=" + range.start + '-' + range.end
      var opts = {"headers": {"Range": rangestr} }

      var stream = file.createStream(opts)
      stream.end()
      return stream
    }

    // first, get the head for the content length.
    // IMPORTANT: servers without HEAD will not work.
    var head = file.createStream({method: 'HEAD'})
    head.on('response', function() {
      if (!/2\d\d/.test(head.res.statusCode))
        cb(new Error("request failed"))

      // get the file length
      file.length = head.res.headers['content-length']
      console.log('found stream of length ' + file.length)

      // ok it worked. add the file.
      file.id = that.entries.push(file) - 1
      that.emit('update')
      cb()
    })

    head.on('error', function(err) {
      console.log(err)
      cb(err)
    })

    head.end()
  }

  var onipfslink = function (link, cb) {
    var local = "localhost:8080" // todo: make this configurable
    var gateway = "gateway.ipfs.io"
    var file = {}

    // first, try the local http gateway
    console.log('trying local ipfs gateway at ' + local)
    var u = "http://" + local + link
    onhttplink(u, function(err) {
      if (!err) return cb() // done.

      // error? ok try fuse... maybe the gateway's broken.
      console.log('trying mounted ipfs fs (just in case)')
      onfile(link, function(err) {
        if (!err) return cb() // done.

        // worst case, try global ipfs gateway.
        console.log('trying ipfs global gateway')
        var u = "http://" + gateway + link
        onhttplink(u, function(err) {
          cb(new Error("failed to find ipfs gateway. is ipfs running?"))
        })
      })
    })
  }

  that.selected = null

  that.deselect = function () {
    that.selected = null
    that.emit('deselect')
  }

  that.selectNext = function () {
    if (!that.entries.length) return null
    if (!that.selected) return that.select(0)
    if (that.selected.id === that.entries.length - 1) return null
    return that.select(that.selected.id + 1)
  }

  that.select = function (id) {
    that.selected = that.get(id)
    that.emit('select')
    return that.selected
  }

  that.get = function (id) {
    return that.entries[id]
  }

  that.add = function (link, cb) {
    if (!cb) cb = noop
    if (/magnet:/.test(link)) return onmagnet(link, cb)
    if (/\.torrent$/i.test(link)) return ontorrent(link, cb)
    if (/youtube\.com\/watch/i.test(link)) return onyoutube(link, cb)
    if (/^\/(ipfs|ipns)\//i.test(link)) return onipfslink(link, cb)
    if (/^\/https?:\/\//i.test(link)) return onhttplink(link, cb)
    onfile(link, cb)
  }

  return that
}<|endoftext|>


<commit_before>/*
 * Copyright 2013 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');
var fs = require('fs');
var tz = require('timezone-js');
var railsTimezone = require('rails-timezone');

var RailsMappings = require('oae-util/timezones-rails');

tz.timezone.loadingScheme = tz.timezone.loadingSchemes.MANUAL_LOAD;
tz.timezone.transport = function(opts) {
    return fs.readFileSync(opts.url, 'utf8');
};
tz.timezone.loadZoneJSONData(__dirname + '/../timezones.json', true);

module.exports = tz;

/**
 * Given a ruby-on-rails supported timezone name, map it to a TZInfo identifier supported by OAE.
 *
 * @param  {String}    zone   The rails timezone to map
 * @return {String}           The TZInfo identifier that represents the associated rails timezone
 */
var getTimezoneFromRails = module.exports.getTimezoneFromRails = function(zone) {
    return railsTimezone.from(zone);
};

/**
 * Given a TZInfo timezone name, get the closest TZInfo zone that is in the rails supported list
 *
 * @param  {String}    zone   The TZInfo timezone to map
 * @return {String}           The associated rails timezone
 */
var getClosestSupportedTimezone = module.exports.getClosestSupportedTimezone = function(zone) {
    // If no zone was passed in just return Etc/UTC
    if (!zone) {
        return 'Etc/UTC';
    }
    // If there's a direct mapping just return it
    if (railsTimezone.to(zone)) {
        return zone;
    }
    // Otherwise we'll guess a zone based on the offset

    // Get the current offsets for all rails zones
    try {
        var railsOffsets = {};
        _.each(RailsMappings, function(value, key) {
            var mappingDate = new tz.Date(value);
            var mappingOffset = mappingDate.getTimezoneOffset();
            if (railsOffsets[mappingOffset]) {
                railsOffsets[mappingOffset].push(value);
            } else {
                railsOffsets[mappingOffset] = [value];
            }
        });
        var userOffset = new tz.Date(zone).getTimezoneOffset();
        // If there's a zone with a matching offset return it
        if (railsOffsets[userOffset]) {
            return railsOffsets[userOffset].sort()[0];
        }
        // No matching offset, return the zone with the closest offset
        var availableOffsets = _.keys(railsOffsets);
        // Offsets are in minutes, 1440 is 24 hours
        var closest = {'delta': 1440, 'zone': null};
        _.each(railsOffsets, function(zone, offset) {
            var delta = Math.abs(offset - userOffset);
            if (delta < closest.delta) {
                closest = {
                    'delta': delta,
                    'zone': zone.sort()[0]
                };
            }
        });
        return closest.zone;
    } catch(err) {
        // If someone passes in a bad zone name we end up here
        return;
    }
};

/**
 * Gets a list of available timezones with their current offset from UTC
 *
 * @return {Object}        A map of all the available rails timezones and their offsets from UTC
 */
var getZones = module.exports.getZones = function() {
    var railsZones = {};
    _.each(RailsMappings, function(value, key) {
        var mappingDate = new tz.Date(value);
        railsZones[value] = {
            'displayName': key,
            // Send the offset in hours
            'offset': mappingDate.getTimezoneOffset() / 60
        };
    });
    return railsZones;
};
<commit_msg>Added a TODO for better timezone matching + documentation fixes<commit_after>/*
 * Copyright 2013 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');
var fs = require('fs');
var tz = require('timezone-js');
var railsTimezone = require('rails-timezone');

var RailsMappings = require('oae-util/timezones-rails');

tz.timezone.loadingScheme = tz.timezone.loadingSchemes.MANUAL_LOAD;
tz.timezone.transport = function(opts) {
    return fs.readFileSync(opts.url, 'utf8');
};
tz.timezone.loadZoneJSONData(__dirname + '/../timezones.json', true);

module.exports = tz;

/**
 * Given a ruby-on-rails supported timezone name, map it to a TZInfo identifier supported by OAE.
 *
 * @param  {String}    zone   The rails timezone to map
 * @return {String}           The TZInfo identifier that represents the associated rails timezone
 */
var getTimezoneFromRails = module.exports.getTimezoneFromRails = function(zone) {
    return railsTimezone.from(zone);
};

/**
 * Given a TZInfo timezone name, get the closest TZInfo zone that is in the rails supported list
 *
 * TODO: Find a way in which better timezone matching can be done, rather than alphabetically sorting
 *       and using the first one. See https://github.com/oaeproject/Hilary/issues/555.
 *
 * @param  {String}    zone   The TZInfo timezone to map
 * @return {String}           The associated rails timezone
 */
var getClosestSupportedTimezone = module.exports.getClosestSupportedTimezone = function(zone) {
    // If no zone was passed in just return Etc/UTC
    if (!zone) {
        return 'Etc/UTC';
    }
    // If there's a direct mapping just return it
    if (railsTimezone.to(zone)) {
        return zone;
    }
    // Otherwise we'll guess a zone based on the offset

    // Get the current offsets for all rails zones
    try {
        // Collect all of the supported timezones per timezone offset
        var railsOffsets = {};
        _.each(RailsMappings, function(value, key) {
            var mappingDate = new tz.Date(value);
            var mappingOffset = mappingDate.getTimezoneOffset();
            if (railsOffsets[mappingOffset]) {
                railsOffsets[mappingOffset].push(value);
            } else {
                railsOffsets[mappingOffset] = [value];
            }
        });
        var userOffset = new tz.Date(zone).getTimezoneOffset();
        // If there's a zone with a matching offset, sort the timezones with that
        // offset alphabetically and return the first one.
        if (railsOffsets[userOffset]) {
            return railsOffsets[userOffset].sort()[0];
        }
        // No matching offset, find the zone with the closest offset, sort the timezones
        // with that offset alphabetically and return the first one.
        var availableOffsets = _.keys(railsOffsets);
        // Offsets are in minutes, 1440 is 24 hours
        var closest = {'delta': 1440, 'zone': null};
        _.each(railsOffsets, function(zone, offset) {
            var delta = Math.abs(offset - userOffset);
            if (delta < closest.delta) {
                closest = {
                    'delta': delta,
                    'zone': zone.sort()[0]
                };
            }
        });
        return closest.zone;
    } catch(err) {
        // If someone passes in a bad zone name we end up here
        return;
    }
};

/**
 * Gets a list of available timezones with their current offset from UTC
 *
 * @return {Object}        A map of all the available rails timezones and their offsets from UTC
 */
var getZones = module.exports.getZones = function() {
    var railsZones = {};
    _.each(RailsMappings, function(value, key) {
        var mappingDate = new tz.Date(value);
        railsZones[value] = {
            'displayName': key,
            // Send the offset in hours
            'offset': mappingDate.getTimezoneOffset() / 60
        };
    });
    return railsZones;
};
<|endoftext|>


<commit_before>if (!window.fetch) window.fetch = require('unfetch').default || require('unfetch');
<commit_msg>ammend #32 to go back to "."<commit_after>if (!window.fetch) window.fetch = require('.').default || require('.');
<|endoftext|>


<commit_before>if (!window.fetch) window.fetch = require('.');<commit_msg>Fix polyfill in webpack 2<commit_after>if (!window.fetch) window.fetch = require('unfetch').default || require('unfetch');
<|endoftext|>


<commit_before>// not "use strict" so we can declare global "Promise"

var asap = require('asap');

if (typeof Promise === 'undefined') {
  Promise = require('./lib/core.js')
  require('./lib/es6-extensions.js')
}

require('./polfill-done.js');
<commit_msg>Fix typo in polyfill.js<commit_after>// not "use strict" so we can declare global "Promise"

var asap = require('asap');

if (typeof Promise === 'undefined') {
  Promise = require('./lib/core.js')
  require('./lib/es6-extensions.js')
}

require('./polyfill-done.js');
<|endoftext|>