<commit_before>/**
 * Jadu Homepages
 *
 * The UI for the new Homepages
 */
define([
  'jquery',
  'jquery-ui',
  'jquery-ui-touch'
], function() {
    (function ($, window, document, undefined) {

        var dragging = false,
            resizing = false,
            rowDragging = false,
            originalX = 0,
            currentX = 0,
            originalY = 0,
            currentY = 0,
            columnsResized = 0,
            alreadyResized = false,
            columnCount = 12,
            widgetPath = '/var/widgets/',
            homepagePath = '/var/homepages/',
            versions = [];

        function attachEvents(element) {
            $(element).on('mousedown', '.homepage-widget', function(e){
                e.preventDefault();
                resizing = false;
                dragging = true;
                originalX = e.pageX;
                $(this).addClass('operating');
            });

            $(element).on('mousedown', '.row-handler', function(e){
                e.stopPropagation();
                e.preventDefault();
                rowDragging = true;
                originalY = e.pageY;
                $(this).parent().addClass('operating-row');
            });

            $(element).on('mousedown', '.resizer', function(e){
                e.stopPropagation();
                e.preventDefault();
                resizing = true;
                originalX = e.pageX;
                $(this).parent().addClass('operating');
            }).on('mouseup', function(e){
                e.preventDefault();
            });

            $('body').on('mousemove', function(e){
                if(dragging) {
                    var operator = $('.operating');
                    currentX = e.pageX;
                    var diffX = currentX - originalX;
                    if(diffX > 60) {
                        if(operator.next().length) {
                            operator.next().after(operator);
                            diffX = 0;
                            originalX = e.pageX;
                        }
                        else if(diffX > 90) {
                            manipulateOffset(operator, 'right');
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                    else if(diffX < -60) {
                        if(!operator.is('[class*=offset]') && operator.prev('.homepage-widget').length) {
                            operator.prev('.homepage-widget').before(operator);
                            diffX = 0;
                            originalX = e.pageX;
                        }
                        else if(diffX < -90) {
                            manipulateOffset(operator, 'left');
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                }
                if(rowDragging) {
                    var operatingRow = $('.operating-row');
                    currentY = e.pageY;
                    var diffY = currentY - originalY;
                    if(diffY < -100) {
                        if(operatingRow.prev('.widget-row').length) {
                            operatingRow.prev('.widget-row').before(operatingRow);
                            diffY = 0;
                            originalY = e.pageY;
                        }
                    }
                    else if(diffY > 100) {
                        if(operatingRow.next('.widget-row').length) {
                            operatingRow.next('.widget-row').after(operatingRow);
                            diffY = 0;
                            originalY = e.pageY;
                        }
                    }
                }
                if(resizing) {
                    var columnWidth = parseInt($('.grid-span-1').outerWidth());
                    var columnMargin = parseInt($('.grid-span-1').css('margin-right')) + 1;
                    columnWidth += columnMargin;
                    currentX = e.pageX;
                    var diffX = currentX - originalX;
                    if(diffX > columnWidth - (columnWidth / 10)) {
                        var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                        var oldSpan = 'grid-span-' + operatingSpan;
                        operatingSpan += columnsResized;
                        if(operatingSpan < columnCount) {
                            columnsResized += 1;
                            var indicatorWidth = parseInt($('.operating .resizer .indicator').outerWidth());
                            indicatorWidth += columnWidth;
                            $('.operating .resizer .indicator').css({ width : indicatorWidth + 'px', right : '-' + indicatorWidth + 'px'});
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                    else if(diffX < -60) {
                        var indicatorWidth = parseInt($('.operating .resizer .indicator').outerWidth());
                        indicatorWidth -= columnWidth;
                        $('.operating .resizer .indicator').css({ width : indicatorWidth + 'px', right : '-' + indicatorWidth + 'px'});
                        diffX = 0;
                        originalX = e.pageX;
                        columnsResized -= 1;
                        if(columnsResized < 0) {
                            var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                            var oldSpan = 'grid-span-' + operatingSpan;
                            operatingSpan += columnsResized;
                            if(operatingSpan < 1) {
                                operatingSpan = 1;
                            }
                            else if(operatingSpan > 12) {
                                operatingSpan = 12;
                            }
                            var newSpan = 'grid-span-' + operatingSpan;
                            $('.operating').removeClass(oldSpan).addClass(newSpan);
                            $('.operating .resizer .indicator').css({width : '0', right : '0' });
                            columnsResized = 0;
                        }
                    }
                }
            }).on('mouseup', function(e){
                if(resizing) {
                    if(!alreadyResized) {
                        var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                        var oldSpan = 'grid-span-' + operatingSpan;
                        operatingSpan += columnsResized;
                        if(operatingSpan < 1) {
                            operatingSpan = 1;
                        }
                        else if(operatingSpan > 12) {
                            operatingSpan = 12;
                        }
                        var newSpan = 'grid-span-' + operatingSpan;
                        $('.operating').removeClass(oldSpan).addClass(newSpan);
                        $('.operating .resizer .indicator').css({width : '0', right : '0' });
                        $('.operating').removeClass('operating');
                    }
                    columnsResized = 0;
                    resizing = false;
                }
                if(dragging) {
                    dragging = false;
                    $('.operating').removeClass('operating');
                }
                if(rowDragging) {
                    rowDragging = false;
                    $('.operating-row').removeClass('operating-row');
                }
            });

            $('.focus').on('click', function(e){
                $('#top, footer').slideToggle();
                $('.grid-master').fadeToggle();
            });
        }

        function createHomepageObject(element) {
            var homepageObject = [];
            var i = 0;
            element.children('.widget-row').each(function(){
                var row = [];
                var thisRow = $(this);
                thisRow.children('.homepage-widget').each(function(){
                    var thisWidget = $(this);
                    var widget = {};
                    var widgetClass = thisWidget.attr('class');
                    var widgetGuid = thisWidget.data('widget-guid');
                    var widgetVersion = thisWidget.data('widget-version');
                    widget = { classes: widgetClass, guid: widgetGuid, version: widgetVersion};
                    row.push(widget);
                });
                homepageObject.push(row);
            });
            return homepageObject;
        }

        function paintHomepage(element, homepage) {
            var homepageDOM = $('

');
            var resizer = '

';
            var resizerLeft = $('

');
            homepage.forEach(function(homepageRow, index){
                var rowDOM = $('

');
                var rowHandler = $('

');
                var rowNo = parseInt(index) + 1;
                var rowTitle = 'Row ' + rowNo;
                rowHandler.append(rowTitle);
                rowDOM.append(rowHandler);
                var widgetCount = homepageRow.length;
                function ajaxLoop(widgetIndex, rowArray) {
                    var widget = rowArray[widgetIndex];
                    var guid = widget.guid;
                    var version = widget.version;
                    var classes = widget.classes;
                    var loadingSpinner = $('

');
                    loadingSpinner.addClass(classes).append(resizer);
                    rowDOM.append(loadingSpinner);
                    $.ajax({
                      url: widgetPath + guid + '/' + version + '/index.php',
                      success: function (data) {
                            var dataElement = $(data);
                            var newIndex = widgetIndex + 1;
                            loadingSpinner.remove('h2').append(dataElement);
                            if(newIndex < widgetCount) {
                                var widget = rowArray[widgetIndex + 1];
                                ajaxLoop(newIndex, rowArray);
                            }
                            else {
                                homepageDOM.append(rowDOM);
                            }
                        }
                    });
                }
                ajaxLoop(0, homepageRow);
            });
            element.append(homepageDOM);
        }

        function loadHomepageObject(json, element) {
            console.log(json);
            var homepageLiteral = $.parseJSON(json);
            paintHomepage(element, homepageLiteral);
            // attachEvents();
        }

        function fetchHomepage(guid, element) {
            $.ajax({
                url: homepagePath + '/' + guid + '.json'
            }).done(function (data) {
                loadHomepageObject(data, element);
            });
            attachEvents(element);
        }

        var homepageContainer = $('.homepage-content');
        fetchHomepage('fillmurray', homepageContainer);

        function manipulateOffset(operator, direction) {
            if(!(operator.is('[class*=offset]')) && direction == 'right') {
                operator.addClass('offset-1');
            }
            else if(direction == 'right') {
                var operatingOffset = parseInt(operator.attr('class').split('offset-')[1].split(' ')[0]);
                var oldOffset = 'offset-' + operatingOffset;
                operatingOffset += 1;
                var newOffset = 'offset-' + operatingOffset;
                operator.removeClass(oldOffset).addClass(newOffset)
            }
            else if(direction == 'left') {
                var operatingOffset = parseInt(operator.attr('class').split('offset-')[1].split(' ')[0]);
                var oldOffset = 'offset-' + operatingOffset;
                operatingOffset -= 1;
                if(operatingOffset == 0) {
                    operator.removeClass(oldOffset);
                }
                else {
                    var newOffset = 'offset-' + operatingOffset;
                    operator.removeClass(oldOffset).addClass(newOffset)
                }
            }
        }

    })(jQuery, window, document);
});<commit_msg>Fix issue where cursor becomes 'detached' when resizing a widget back and forth [CMP-3]<commit_after>/**
 * Jadu Homepages
 *
 * The UI for the new Homepages
 */
define([
  'jquery',
  'jquery-ui',
  'jquery-ui-touch'
], function() {
    (function ($, window, document, undefined) {

        var dragging = false,
            resizing = false,
            rowDragging = false,
            originalX = 0,
            currentX = 0,
            originalY = 0,
            currentY = 0,
            columnsResized = 0,
            alreadyResized = false,
            columnCount = 12,
            widgetPath = '/var/widgets/',
            homepagePath = '/var/homepages/',
            versions = [];

        function attachEvents(element) {
            $(element).on('mousedown', '.homepage-widget', function(e){
                e.preventDefault();
                resizing = false;
                dragging = true;
                originalX = e.pageX;
                $(this).addClass('operating');
            });

            $(element).on('mousedown', '.row-handler', function(e){
                e.stopPropagation();
                e.preventDefault();
                rowDragging = true;
                originalY = e.pageY;
                $(this).parent().addClass('operating-row');
            });

            $(element).on('mousedown', '.resizer', function(e){
                e.stopPropagation();
                e.preventDefault();
                resizing = true;
                originalX = e.pageX;
                $(this).parent().addClass('operating');
            }).on('mouseup', function(e){
                e.preventDefault();
            });

            $('body').on('mousemove', function(e){
                if(dragging) {
                    var operator = $('.operating');
                    currentX = e.pageX;
                    var diffX = currentX - originalX;
                    if(diffX > 60) {
                        if(operator.next().length) {
                            operator.next().after(operator);
                            diffX = 0;
                            originalX = e.pageX;
                        }
                        else if(diffX > 90) {
                            manipulateOffset(operator, 'right');
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                    else if(diffX < -60) {
                        if(!operator.is('[class*=offset]') && operator.prev('.homepage-widget').length) {
                            operator.prev('.homepage-widget').before(operator);
                            diffX = 0;
                            originalX = e.pageX;
                        }
                        else if(diffX < -90) {
                            manipulateOffset(operator, 'left');
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                }
                if(rowDragging) {
                    var operatingRow = $('.operating-row');
                    currentY = e.pageY;
                    var diffY = currentY - originalY;
                    if(diffY < -100) {
                        if(operatingRow.prev('.widget-row').length) {
                            operatingRow.prev('.widget-row').before(operatingRow);
                            diffY = 0;
                            originalY = e.pageY;
                        }
                    }
                    else if(diffY > 100) {
                        if(operatingRow.next('.widget-row').length) {
                            operatingRow.next('.widget-row').after(operatingRow);
                            diffY = 0;
                            originalY = e.pageY;
                        }
                    }
                }
                if(resizing) {
                    var columnWidth = parseInt($('.grid-span-1').outerWidth());
                    var columnMargin = parseInt($('.grid-span-1').css('margin-right')) + 1;
                    columnWidth += columnMargin;
                    currentX = e.pageX;
                    var diffX = currentX - originalX;
                    if(diffX > columnWidth) {
                        var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                        var oldSpan = 'grid-span-' + operatingSpan;
                        operatingSpan += columnsResized;
                        if(operatingSpan < columnCount) {
                            columnsResized += 1;
                            var indicatorWidth = parseInt($('.operating .resizer .indicator').outerWidth());
                            indicatorWidth += columnWidth;
                            $('.operating .resizer .indicator').css({ width : indicatorWidth + 'px', right : '-' + indicatorWidth + 'px'});
                            diffX = 0;
                            originalX = e.pageX;
                        }
                    }
                    else if(diffX < -columnWidth) {
                        var indicatorWidth = parseInt($('.operating .resizer .indicator').outerWidth());
                        indicatorWidth -= columnWidth;
                        $('.operating .resizer .indicator').css({ width : indicatorWidth + 'px', right : '-' + indicatorWidth + 'px'});
                        diffX = 0;
                        originalX = e.pageX;
                        columnsResized -= 1;
                        if(columnsResized < 0) {
                            var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                            var oldSpan = 'grid-span-' + operatingSpan;
                            operatingSpan += columnsResized;
                            if(operatingSpan < 1) {
                                operatingSpan = 1;
                            }
                            else if(operatingSpan > 12) {
                                operatingSpan = 12;
                            }
                            var newSpan = 'grid-span-' + operatingSpan;
                            $('.operating').removeClass(oldSpan).addClass(newSpan);
                            $('.operating .resizer .indicator').css({width : '0', right : '0' });
                            columnsResized = 0;
                        }
                    }
                }
            }).on('mouseup', function(e){
                if(resizing) {
                    if(!alreadyResized) {
                        var operatingSpan = parseInt($('.operating').attr('class').split('grid-span-')[1].split(' ')[0]);
                        var oldSpan = 'grid-span-' + operatingSpan;
                        operatingSpan += columnsResized;
                        if(operatingSpan < 1) {
                            operatingSpan = 1;
                        }
                        else if(operatingSpan > 12) {
                            operatingSpan = 12;
                        }
                        var newSpan = 'grid-span-' + operatingSpan;
                        $('.operating').removeClass(oldSpan).addClass(newSpan);
                        $('.operating .resizer .indicator').css({width : '0', right : '0' });
                        $('.operating').removeClass('operating');
                    }
                    columnsResized = 0;
                    resizing = false;
                }
                if(dragging) {
                    dragging = false;
                    $('.operating').removeClass('operating');
                }
                if(rowDragging) {
                    rowDragging = false;
                    $('.operating-row').removeClass('operating-row');
                }
            });

            $('.focus').on('click', function(e){
                $('#top, footer').slideToggle();
                $('.grid-master').fadeToggle();
            });
        }

        function createHomepageObject(element) {
            var homepageObject = [];
            var i = 0;
            element.children('.widget-row').each(function(){
                var row = [];
                var thisRow = $(this);
                thisRow.children('.homepage-widget').each(function(){
                    var thisWidget = $(this);
                    var widget = {};
                    var widgetClass = thisWidget.attr('class');
                    var widgetGuid = thisWidget.data('widget-guid');
                    var widgetVersion = thisWidget.data('widget-version');
                    widget = { classes: widgetClass, guid: widgetGuid, version: widgetVersion};
                    row.push(widget);
                });
                homepageObject.push(row);
            });
            return homepageObject;
        }

        function paintHomepage(element, homepage) {
            var homepageDOM = $('

');
            var resizer = '

';
            var resizerLeft = $('

');
            homepage.forEach(function(homepageRow, index){
                var rowDOM = $('

');
                var rowHandler = $('

');
                var rowNo = parseInt(index) + 1;
                var rowTitle = 'Row ' + rowNo;
                rowHandler.append(rowTitle);
                rowDOM.append(rowHandler);
                var widgetCount = homepageRow.length;
                function ajaxLoop(widgetIndex, rowArray) {
                    var widget = rowArray[widgetIndex];
                    var guid = widget.guid;
                    var version = widget.version;
                    var classes = widget.classes;
                    var loadingSpinner = $('

');
                    loadingSpinner.addClass(classes).append(resizer);
                    rowDOM.append(loadingSpinner);
                    $.ajax({
                      url: widgetPath + guid + '/' + version + '/index.php',
                      success: function (data) {
                            var dataElement = $(data);
                            var newIndex = widgetIndex + 1;
                            loadingSpinner.remove('h2').append(dataElement);
                            if(newIndex < widgetCount) {
                                var widget = rowArray[widgetIndex + 1];
                                ajaxLoop(newIndex, rowArray);
                            }
                            else {
                                homepageDOM.append(rowDOM);
                            }
                        }
                    });
                }
                ajaxLoop(0, homepageRow);
            });
            element.append(homepageDOM);
        }

        function loadHomepageObject(json, element) {
            console.log(json);
            var homepageLiteral = $.parseJSON(json);
            paintHomepage(element, homepageLiteral);
            // attachEvents();
        }

        function fetchHomepage(guid, element) {
            $.ajax({
                url: homepagePath + '/' + guid + '.json'
            }).done(function (data) {
                loadHomepageObject(data, element);
            });
            attachEvents(element);
        }

        var homepageContainer = $('.homepage-content');
        fetchHomepage('fillmurray', homepageContainer);

        function manipulateOffset(operator, direction) {
            if(!(operator.is('[class*=offset]')) && direction == 'right') {
                operator.addClass('offset-1');
            }
            else if(direction == 'right') {
                var operatingOffset = parseInt(operator.attr('class').split('offset-')[1].split(' ')[0]);
                var oldOffset = 'offset-' + operatingOffset;
                operatingOffset += 1;
                var newOffset = 'offset-' + operatingOffset;
                operator.removeClass(oldOffset).addClass(newOffset)
            }
            else if(direction == 'left') {
                var operatingOffset = parseInt(operator.attr('class').split('offset-')[1].split(' ')[0]);
                var oldOffset = 'offset-' + operatingOffset;
                operatingOffset -= 1;
                if(operatingOffset == 0) {
                    operator.removeClass(oldOffset);
                }
                else {
                    var newOffset = 'offset-' + operatingOffset;
                    operator.removeClass(oldOffset).addClass(newOffset)
                }
            }
        }

    })(jQuery, window, document);
});<|endoftext|>


<commit_before>import "convert.js";
import "item.js";

'use strict';

KB.Item.Editor = React.createClass({
	blur: function(ev){
		var container = this.getDOMNode();
		if(!container.contains(ev.relatedTarget)){
			this.commit();
		}
	},
	commit: function(ev){
		var stage = this.props.stage,
			item = this.props.item;

		var text = this.refs.text.getDOMNode().value;
		if((text === '') &&
			((item.type === 'paragraph') || (item.type === 'html'))){
			stage.patch({
				id: item.id,
				type: "remove"
			});
			return;
		}

		if(item.text != text){
			var next = DeepClone(item);
			next.text = text;
			stage.patch({
				id: next.id,
				type: "edit",
				item: next
			})
		}
		this.stopEditing();
	},
	stopEditing: function(){
		var stage = this.props.stage,
			item = this.props.item;

		try {
			var actual = stage.page.itemById(item.id);
			if(actual && (actual.type == "paragraph") && (actual.text == "")){
				stage.patch({
					id: actual.id,
					type: "remove"
				});
			}
		} catch(ex){}

		stage.editing.stop(item.id);
	},

	remove: function(ev){
		var stage = this.props.stage,
			item = this.props.item;

		stage.patch({
			type: 'remove',
			id: item.id
		});

		ev.preventDefault();
		ev.stopPropagation();
	},

	handleKey: function(ev){
		if(ev.keyCode == 27){
			this.stopEditing();
			ev.preventDefault();
			ev.stopPropagation();
			return;
		}

		var stage = this.props.stage,
			item = this.props.item,
			node = this.refs.text.getDOMNode();

		if((ev.ctrlKey) && (ev.keyCode == 13)){

			var pre = node.value.substr(0, node.selectionStart),
				post = node.value.substr(node.selectionStart);

			if(pre == ""){
				ev.preventDefault();
				return;
			}

			if(pre != node.value){
				node.value = pre;
				this.commit();
				this.stopEditing();
			}

			var continueWith = {
				"paragraph": "paragraph",
				"html": "html"
			};

			var adding = {
				type: continueWith[item.type] || "paragraph",
				id: GenerateID(),
				text: post
			};

			stage.patch({
				type: 'add',
				id: adding.id,
				after: item.id,
				item: adding
			});

			stage.editing.start(adding.id);
			ev.preventDefault();
		}
	},
	render: function(){
		var stage = this.props.stage,
			item = this.props.item;
		return React.DOM.div(
			{
				className: "item-content content-editor",
				onBlur: this.blur
			},
			React.DOM.div({className: "item-type"}, item.type),
			React.DOM.textarea({
				ref: "text",
				defaultValue: item.text,
				onKeyDown: this.handleKey,
				autoFocus: true
			}),
			React.DOM.div(
				{className:'editor-buttons'},
				React.DOM.div({
					className: "mdi mdi-content-save",
					title: "Save changes. (Unfocus the editor will save.)",
					tabIndex: '1',
					onClick: this.commit
				}),
				React.DOM.div({
					className: "mdi mdi-backup-restore",
					title: "Cancel any modifications. (Pressing escape will cancel changes.)",
					tabIndex: '2',
					onClick: this.stopEditing
				}),
				React.DOM.div({
					className: "item-delete mdi mdi-delete",
					title: "Delete this item.",
					tabIndex: '3',
					onClick: this.remove
				})
			)
		)
	}
});
<commit_msg>Fix FFX item editor buttons.<commit_after>import "convert.js";
import "item.js";

'use strict';

KB.Item.Editor = React.createClass({
	blur: function(ev){
		var self = this;
		var container = this.getDOMNode();
		if(ev.relatedTarget === null){
			// HACK-FIX: Firefox doesn't have relatedTarget
			// use a delayed commit if we don't know the related target
			// that way any menu action can complete, before the commit
			window.setTimeout(function(){ self.commit(); }, 300);
			return;
		}
		if(!container.contains(ev.relatedTarget)){
			this.commit();
		}
	},
	commit: function(ev){
		var stage = this.props.stage,
			item = this.props.item;

		// in case the delay
		if(this.refs.text === undefined) { return; }

		var text = this.refs.text.getDOMNode().value;
		if((text === '') &&
			((item.type === 'paragraph') || (item.type === 'html'))){
			stage.patch({
				id: item.id,
				type: "remove"
			});
			return;
		}

		if(item.text != text){
			var next = DeepClone(item);
			next.text = text;
			stage.patch({
				id: next.id,
				type: "edit",
				item: next
			})
		}
		this.stopEditing();
	},
	stopEditing: function(){
		var stage = this.props.stage,
			item = this.props.item;

		try {
			var actual = stage.page.itemById(item.id);
			if(actual && (actual.type == "paragraph") && (actual.text == "")){
				stage.patch({
					id: actual.id,
					type: "remove"
				});
			}
		} catch(ex){}

		stage.editing.stop(item.id);
	},

	remove: function(ev){
		var stage = this.props.stage,
			item = this.props.item;

		stage.patch({
			type: 'remove',
			id: item.id
		});

		ev.preventDefault();
		ev.stopPropagation();
	},

	handleKey: function(ev){
		if(ev.keyCode == 27){
			this.stopEditing();
			ev.preventDefault();
			ev.stopPropagation();
			return;
		}

		var stage = this.props.stage,
			item = this.props.item,
			node = this.refs.text.getDOMNode();

		if((ev.ctrlKey) && (ev.keyCode == 13)){

			var pre = node.value.substr(0, node.selectionStart),
				post = node.value.substr(node.selectionStart);

			if(pre == ""){
				ev.preventDefault();
				return;
			}

			if(pre != node.value){
				node.value = pre;
				this.commit();
				this.stopEditing();
			}

			var continueWith = {
				"paragraph": "paragraph",
				"html": "html"
			};

			var adding = {
				type: continueWith[item.type] || "paragraph",
				id: GenerateID(),
				text: post
			};

			stage.patch({
				type: 'add',
				id: adding.id,
				after: item.id,
				item: adding
			});

			stage.editing.start(adding.id);
			ev.preventDefault();
		}
	},
	render: function(){
		var stage = this.props.stage,
			item = this.props.item;
		return React.DOM.div(
			{
				className: "item-content content-editor",
				onBlur: this.blur
			},
			React.DOM.div({className: "item-type"}, item.type),
			React.DOM.textarea({
				ref: "text",
				defaultValue: item.text,
				onKeyDown: this.handleKey,
				autoFocus: true
			}),
			React.DOM.div(
				{className:'editor-buttons'},
				React.DOM.div({
					className: "mdi mdi-content-save",
					title: "Save changes. (Unfocus the editor will save.)",
					tabIndex: '1',
					onClick: this.commit
				}),
				React.DOM.div({
					className: "mdi mdi-backup-restore",
					title: "Cancel any modifications. (Pressing escape will cancel changes.)",
					tabIndex: '2',
					onClick: this.stopEditing
				}),
				React.DOM.div({
					className: "item-delete mdi mdi-delete",
					title: "Delete this item.",
					tabIndex: '3',
					onClick: this.remove
				})
			)
		)
	}
});
<|endoftext|>


<commit_before>"use strict";

const $ = require("jquery");
const Mousetrap = require("mousetrap");
const wrapCursor = require("undate").wrapCursor;
const utils = require("./utils");
const form = $("#form");
const input = $("#input");
const sidebar = $("#sidebar");
const windows = $("#windows");

Mousetrap.bind([
	"pageup",
	"pagedown",
], function(e, key) {
	let container = windows.find(".window.active");

	// Chat windows scroll message container
	if (container.prop("id") === "chat-container") {
		container = container.find(".chan.active .chat");
	}

	container.finish();

	const offset = container.get(0).clientHeight * 0.9;
	let scrollTop = container.scrollTop();

	if (key === "pageup") {
		scrollTop = Math.floor(scrollTop - offset);
	} else {
		scrollTop = Math.ceil(scrollTop + offset);
	}

	container.animate({scrollTop}, 200);

	return false;
});

Mousetrap.bind([
	"alt+up",
	"alt+down",
], function(e, keys) {
	const channels = sidebar.find(".chan").not(".network.collapsed :not(.lobby)");
	const index = channels.index(channels.filter(".active"));
	const direction = keys.split("+").pop();
	let target;

	switch (direction) {
	case "up":
		target = (channels.length + (index - 1 + channels.length)) % channels.length;
		break;

	case "down":
		target = (channels.length + (index + 1 + channels.length)) % channels.length;
		break;
	}

	target = channels.eq(target).click();
	utils.scrollIntoViewNicely(target[0]);

	return false;
});

Mousetrap.bind([
	"alt+shift+up",
	"alt+shift+down",
], function(e, keys) {
	const lobbies = sidebar.find(".lobby");
	const direction = keys.split("+").pop();
	let index = lobbies.index(lobbies.filter(".active"));
	let target;

	switch (direction) {
	case "up":
		if (index < 0) {
			target = lobbies.index(sidebar.find(".channel").filter(".active").siblings(".lobby")[0]);
		} else {
			target = (lobbies.length + (index - 1 + lobbies.length)) % lobbies.length;
		}

		break;

	case "down":
		if (index < 0) {
			index = lobbies.index(sidebar.find(".channel").filter(".active").siblings(".lobby")[0]);
		}

		target = (lobbies.length + (index + 1 + lobbies.length)) % lobbies.length;

		break;
	}

	target = lobbies.eq(target).click();
	utils.scrollIntoViewNicely(target[0]);

	return false;
});

const inputTrap = Mousetrap(input.get(0));

function enableHistory() {
	const history = [""];
	let position = 0;

	input.on("input", () => {
		position = 0;
	});

	inputTrap.bind("enter", function() {
		position = 0;

		if (input.data("autocompleting")) {
			return false;
		}

		const text = input.val();

		if (text.length === 0) {
			return false;
		}

		// Submit the form when pressing enter instead of inserting a new line
		form.trigger("submit");

		// Store new message in history if last message isn't already equal
		if (history[1] !== text) {
			history.splice(1, 0, text);
		}

		return false;
	});

	inputTrap.bind(["up", "down"], function(e, key) {
		if (e.target.selectionStart !== e.target.selectionEnd || input.data("autocompleting")) {
			return;
		}

		if (position === 0) {
			history[position] = input.val();
		}

		if (key === "up") {
			if (position < history.length - 1) {
				position++;
			}
		} else if (position > 0) {
			position--;
		}

		input.val(history[position]);

		return false;
	});
}

enableHistory();

const colorsHotkeys = {
	k: "\x03",
	b: "\x02",
	u: "\x1F",
	i: "\x1D",
	o: "\x0F",
	s: "\x1e",
	m: "\x11",
};

for (const hotkey in colorsHotkeys) {
	inputTrap.bind("mod+" + hotkey, function(e) {
		const modifier = colorsHotkeys[e.key];

		wrapCursor(
			e.target,
			modifier,
			e.target.selectionStart === e.target.selectionEnd ? "" : modifier
		);

		return false;
	});
}

// Autocomplete bracket and quote characters like in a modern IDE
// For example, select `text`, press `[` key, and it becomes `[text]`
const bracketWraps = {
	'"': '"',
	"'": "'",
	"(": ")",
	"<": ">",
	"[": "]",
	"{": "}",
	"*": "*",
	"`": "`",
	"~": "~",
	"_": "_",
};

inputTrap.bind(Object.keys(bracketWraps), function(e) {
	if (e.target.selectionStart !== e.target.selectionEnd) {
		wrapCursor(e.target, e.key, bracketWraps[e.key]);

		return false;
	}
});

// Ignored keys which should not automatically focus the input bar
const ignoredKeys = {
	8: true, // Backspace
	9: true, // Tab
	12: true, // Clear
	16: true, // Shift
	17: true, // Control
	18: true, // Alt
	19: true, // Pause
	20: true, // CapsLock
	27: true, // Escape
	33: true, // PageUp
	34: true, // PageDown
	35: true, // End
	36: true, // Home
	37: true, // ArrowLeft
	38: true, // ArrowUp
	39: true, // ArrowRight
	40: true, // ArrowDown
	45: true, // Insert
	46: true, // Delete
	112: true, // F1
	113: true, // F2
	114: true, // F3
	115: true, // F4
	116: true, // F5
	117: true, // F6
	118: true, // F7
	119: true, // F8
	120: true, // F9
	121: true, // F10
	122: true, // F11
	123: true, // F12
	144: true, // NumLock
	145: true, // ScrollLock
	224: true, // Meta
};

$(document).on("keydown", (e) => {
	// Ignore any key that uses alt modifier
	// Ignore keys defined above
	if (e.altKey || ignoredKeys[e.which]) {
		return;
	}

	// Ignore all ctrl keys except for ctrl+v to allow pasting
	if ((e.ctrlKey || e.metaKey) && e.which !== 86) {
		return;
	}

	const tagName = e.target.tagName;

	// Ignore if we're already typing into <input> or <textarea>
	if (tagName === "INPUT" || tagName === "TEXTAREA") {
		return;
	}

	// On enter, focus the input but do not propagate the event
	// This way, a new line is not inserted
	if (e.which === 13) {
		input.trigger("focus");
		return false;
	}

	input.trigger("focus");
});
<commit_msg>Fix irc modifiers not working with caps lock<commit_after>"use strict";

const $ = require("jquery");
const Mousetrap = require("mousetrap");
const wrapCursor = require("undate").wrapCursor;
const utils = require("./utils");
const form = $("#form");
const input = $("#input");
const sidebar = $("#sidebar");
const windows = $("#windows");

Mousetrap.bind([
	"pageup",
	"pagedown",
], function(e, key) {
	let container = windows.find(".window.active");

	// Chat windows scroll message container
	if (container.prop("id") === "chat-container") {
		container = container.find(".chan.active .chat");
	}

	container.finish();

	const offset = container.get(0).clientHeight * 0.9;
	let scrollTop = container.scrollTop();

	if (key === "pageup") {
		scrollTop = Math.floor(scrollTop - offset);
	} else {
		scrollTop = Math.ceil(scrollTop + offset);
	}

	container.animate({scrollTop}, 200);

	return false;
});

Mousetrap.bind([
	"alt+up",
	"alt+down",
], function(e, keys) {
	const channels = sidebar.find(".chan").not(".network.collapsed :not(.lobby)");
	const index = channels.index(channels.filter(".active"));
	const direction = keys.split("+").pop();
	let target;

	switch (direction) {
	case "up":
		target = (channels.length + (index - 1 + channels.length)) % channels.length;
		break;

	case "down":
		target = (channels.length + (index + 1 + channels.length)) % channels.length;
		break;
	}

	target = channels.eq(target).click();
	utils.scrollIntoViewNicely(target[0]);

	return false;
});

Mousetrap.bind([
	"alt+shift+up",
	"alt+shift+down",
], function(e, keys) {
	const lobbies = sidebar.find(".lobby");
	const direction = keys.split("+").pop();
	let index = lobbies.index(lobbies.filter(".active"));
	let target;

	switch (direction) {
	case "up":
		if (index < 0) {
			target = lobbies.index(sidebar.find(".channel").filter(".active").siblings(".lobby")[0]);
		} else {
			target = (lobbies.length + (index - 1 + lobbies.length)) % lobbies.length;
		}

		break;

	case "down":
		if (index < 0) {
			index = lobbies.index(sidebar.find(".channel").filter(".active").siblings(".lobby")[0]);
		}

		target = (lobbies.length + (index + 1 + lobbies.length)) % lobbies.length;

		break;
	}

	target = lobbies.eq(target).click();
	utils.scrollIntoViewNicely(target[0]);

	return false;
});

const inputTrap = Mousetrap(input.get(0));

function enableHistory() {
	const history = [""];
	let position = 0;

	input.on("input", () => {
		position = 0;
	});

	inputTrap.bind("enter", function() {
		position = 0;

		if (input.data("autocompleting")) {
			return false;
		}

		const text = input.val();

		if (text.length === 0) {
			return false;
		}

		// Submit the form when pressing enter instead of inserting a new line
		form.trigger("submit");

		// Store new message in history if last message isn't already equal
		if (history[1] !== text) {
			history.splice(1, 0, text);
		}

		return false;
	});

	inputTrap.bind(["up", "down"], function(e, key) {
		if (e.target.selectionStart !== e.target.selectionEnd || input.data("autocompleting")) {
			return;
		}

		if (position === 0) {
			history[position] = input.val();
		}

		if (key === "up") {
			if (position < history.length - 1) {
				position++;
			}
		} else if (position > 0) {
			position--;
		}

		input.val(history[position]);

		return false;
	});
}

enableHistory();

const colorsHotkeys = {
	k: "\x03",
	b: "\x02",
	u: "\x1F",
	i: "\x1D",
	o: "\x0F",
	s: "\x1e",
	m: "\x11",
};

for (const hotkey in colorsHotkeys) {
	inputTrap.bind("mod+" + hotkey, function(e) {
		// Key is lowercased because keybinds also get processed if caps lock is on
		const modifier = colorsHotkeys[e.key.toLowerCase()];

		wrapCursor(
			e.target,
			modifier,
			e.target.selectionStart === e.target.selectionEnd ? "" : modifier
		);

		return false;
	});
}

// Autocomplete bracket and quote characters like in a modern IDE
// For example, select `text`, press `[` key, and it becomes `[text]`
const bracketWraps = {
	'"': '"',
	"'": "'",
	"(": ")",
	"<": ">",
	"[": "]",
	"{": "}",
	"*": "*",
	"`": "`",
	"~": "~",
	"_": "_",
};

inputTrap.bind(Object.keys(bracketWraps), function(e) {
	if (e.target.selectionStart !== e.target.selectionEnd) {
		wrapCursor(e.target, e.key, bracketWraps[e.key]);

		return false;
	}
});

// Ignored keys which should not automatically focus the input bar
const ignoredKeys = {
	8: true, // Backspace
	9: true, // Tab
	12: true, // Clear
	16: true, // Shift
	17: true, // Control
	18: true, // Alt
	19: true, // Pause
	20: true, // CapsLock
	27: true, // Escape
	33: true, // PageUp
	34: true, // PageDown
	35: true, // End
	36: true, // Home
	37: true, // ArrowLeft
	38: true, // ArrowUp
	39: true, // ArrowRight
	40: true, // ArrowDown
	45: true, // Insert
	46: true, // Delete
	112: true, // F1
	113: true, // F2
	114: true, // F3
	115: true, // F4
	116: true, // F5
	117: true, // F6
	118: true, // F7
	119: true, // F8
	120: true, // F9
	121: true, // F10
	122: true, // F11
	123: true, // F12
	144: true, // NumLock
	145: true, // ScrollLock
	224: true, // Meta
};

$(document).on("keydown", (e) => {
	// Ignore any key that uses alt modifier
	// Ignore keys defined above
	if (e.altKey || ignoredKeys[e.which]) {
		return;
	}

	// Ignore all ctrl keys except for ctrl+v to allow pasting
	if ((e.ctrlKey || e.metaKey) && e.which !== 86) {
		return;
	}

	const tagName = e.target.tagName;

	// Ignore if we're already typing into <input> or <textarea>
	if (tagName === "INPUT" || tagName === "TEXTAREA") {
		return;
	}

	// On enter, focus the input but do not propagate the event
	// This way, a new line is not inserted
	if (e.which === 13) {
		input.trigger("focus");
		return false;
	}

	input.trigger("focus");
});
<|endoftext|>


<commit_before>// https://tech.yandex.com/maps/doc/jsapi/2.1/quick-start/index-docpage/

/* global ymaps: true */

L.Yandex = L.Layer.extend({

	options: {
		type: 'yandex#map', // 'map', 'satellite', 'hybrid', 'map~vector' | 'overlay', 'skeleton'
		mapOptions: { // https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/Map-docpage/#Map__param-options
			// yandexMapDisablePoiInteractivity: true,
			balloonAutoPan: false,
			suppressMapOpenBlock: true
		},
		overlayOpacity: 0.8,
		minZoom: 0,
		maxZoom: 19
	},

	initialize: function (type, options) {
		if (typeof type === 'object') {
			options = type;
			type = false;
		}
		options = L.Util.setOptions(this, options);
		if (type) { options.type = type; }
		this._isOverlay = options.type.indexOf('overlay') !== -1 ||
		                  options.type.indexOf('skeleton') !== -1;
		this._animatedElements = [];
	},

	_setStyle: function (el, style) {
		for (var prop in style) {
			el.style[prop] = style[prop];
		}
	},

	_initContainer: function (parentEl) {
		var zIndexClass = this._isOverlay ? 'leaflet-overlay-pane' : 'leaflet-tile-pane';
		var _container = L.DomUtil.create('div', 'leaflet-yandex-container leaflet-pane ' + zIndexClass);
		var opacity = this.options.opacity || this._isOverlay && this.options.overlayOpacity;
		if (opacity) {
			L.DomUtil.setOpacity(_container, opacity);
		}
		var auto = {width: '100%', height: '100%'};
		this._setStyle(parentEl, auto);   // need to set this explicitly,
		this._setStyle(_container, auto); // otherwise ymaps fails to follow container size changes
		return _container;
	},

	onAdd: function (map) {
		var mapPane = map.getPane('mapPane');
		if (!this._container) {
			this._container = this._initContainer(mapPane);
			map.once('unload', this._destroy, this);
			this._initApi();
		}
		mapPane.appendChild(this._container);
		if (!this._yandex) { return; }
		this._setEvents(map);
		this._update();
	},

	beforeAdd: function (map) {
		map._addZoomLimit(this);
	},

	onRemove: function (map) {
		map._removeZoomLimit(this);
	},

	_destroy: function (e) {
		if (!this._map || this._map === e.target) {
			if (this._yandex) {
				this._yandex.destroy();
				delete this._yandex;
			}
			delete this._container;
		}
	},

	_setEvents: function (map) {
		var events = {
			move: this._update
		};
		if (this._zoomAnimated) {
			events.zoomanim = this._animateZoom;
			events.zoomend = this._animateZoomEnd;
		}
		map.on(events, this);
		this.once('remove', function () {
			map.off(events, this);
			this._container.remove(); // we do not call this until api is initialized (ymaps API expects DOM element)
		}, this);
	},

	_update: function () {
		var map = this._map;
		var center = map.getCenter();
		this._yandex.setCenter([center.lat, center.lng], map.getZoom());
		var offset = L.point(0,0).subtract(L.DomUtil.getPosition(map.getPane('mapPane')));
		L.DomUtil.setPosition(this._container, offset); // move to visible part of pane
	},

	_resyncView: function () { // for use in addons
		if (!this._map) { return; }
		var ymap = this._yandex;
		this._map.setView(ymap.getCenter(), ymap.getZoom(), {animate: false});
	},

	_animateZoom: function (e) {
		var map = this._map;
		var viewHalf = map.getSize()._divideBy(2);
		var topLeft = map.project(e.center, e.zoom)._subtract(viewHalf)._round();
                var offset = map.project(map.getBounds().getNorthWest(), e.zoom)._subtract(topLeft);
		var scale = map.getZoomScale(e.zoom);
		this._animatedElements.length = 0;
		this._yandex.panes._array.forEach(function (el) {
			if (el.pane instanceof ymaps.pane.MovablePane) {
				var element = el.pane.getElement();
				L.DomUtil.addClass(element, 'leaflet-zoom-animated');
				L.DomUtil.setTransform(element, offset, scale);
				this._animatedElements.push(element);
			}
		},this);
	},

	_animateZoomEnd: function () {
		this._animatedElements.forEach(function (el) {
			L.DomUtil.setTransform(el, 0, 1);
		});
		this._animatedElements.length = 0;
	},

	_initApi: function () { // to be extended in addons
		ymaps.ready(this._initMapObject, this);
	},

	_mapType: function () {
		var shortType = this.options.type;
		if (!shortType || shortType.indexOf('#') !== -1) {
			return shortType;
		}
		return 'yandex#' + shortType;
	},

	_initMapObject: function () {
		ymaps.mapType.storage.add('yandex#overlay', new ymaps.MapType('overlay', []));
		ymaps.mapType.storage.add('yandex#skeleton', new ymaps.MapType('skeleton', ['yandex#skeleton']));
		ymaps.mapType.storage.add('yandex#map~vector', new ymaps.MapType('map~vector', ['yandex#map~vector']));
		var ymap = new ymaps.Map(this._container, {
			center: [0, 0], zoom: 0, behaviors: [], controls: [],
			type: this._mapType()
		}, this.options.mapOptions);

		if (this._isOverlay) {
			ymap.container.getElement().style.background = 'transparent';
		}
		this._container.remove();
		this._yandex = ymap;
		if (this._map) { this.onAdd(this._map); }

		this.fire('load');
	}
});

L.yandex = function (type, options) {
	return new L.Yandex(type, options);
};
<commit_msg>L.Yandex: follow container's size changes<commit_after>// https://tech.yandex.com/maps/doc/jsapi/2.1/quick-start/index-docpage/

/* global ymaps: true */

L.Yandex = L.Layer.extend({

	options: {
		type: 'yandex#map', // 'map', 'satellite', 'hybrid', 'map~vector' | 'overlay', 'skeleton'
		mapOptions: { // https://tech.yandex.com/maps/doc/jsapi/2.1/ref/reference/Map-docpage/#Map__param-options
			// yandexMapDisablePoiInteractivity: true,
			balloonAutoPan: false,
			suppressMapOpenBlock: true
		},
		overlayOpacity: 0.8,
		minZoom: 0,
		maxZoom: 19
	},

	initialize: function (type, options) {
		if (typeof type === 'object') {
			options = type;
			type = false;
		}
		options = L.Util.setOptions(this, options);
		if (type) { options.type = type; }
		this._isOverlay = options.type.indexOf('overlay') !== -1 ||
		                  options.type.indexOf('skeleton') !== -1;
		this._animatedElements = [];
	},

	_setStyle: function (el, style) {
		for (var prop in style) {
			el.style[prop] = style[prop];
		}
	},

	_initContainer: function (parentEl) {
		var zIndexClass = this._isOverlay ? 'leaflet-overlay-pane' : 'leaflet-tile-pane';
		var _container = L.DomUtil.create('div', 'leaflet-yandex-container leaflet-pane ' + zIndexClass);
		var opacity = this.options.opacity || this._isOverlay && this.options.overlayOpacity;
		if (opacity) {
			L.DomUtil.setOpacity(_container, opacity);
		}
		var auto = {width: '100%', height: '100%'};
		this._setStyle(parentEl, auto);   // need to set this explicitly,
		this._setStyle(_container, auto); // otherwise ymaps fails to follow container size changes
		return _container;
	},

	onAdd: function (map) {
		var mapPane = map.getPane('mapPane');
		if (!this._container) {
			this._container = this._initContainer(mapPane);
			map.once('unload', this._destroy, this);
			this._initApi();
		}
		mapPane.appendChild(this._container);
		if (!this._yandex) { return; }
		this._setEvents(map);
		this._update();
	},

	beforeAdd: function (map) {
		map._addZoomLimit(this);
	},

	onRemove: function (map) {
		map._removeZoomLimit(this);
	},

	_destroy: function (e) {
		if (!this._map || this._map === e.target) {
			if (this._yandex) {
				this._yandex.destroy();
				delete this._yandex;
			}
			delete this._container;
		}
	},

	_setEvents: function (map) {
		var events = {
			move: this._update,
			resize: function () {
				this._yandex.container.fitToViewport();
			}
		};
		if (this._zoomAnimated) {
			events.zoomanim = this._animateZoom;
			events.zoomend = this._animateZoomEnd;
		}
		map.on(events, this);
		this.once('remove', function () {
			map.off(events, this);
			this._container.remove(); // we do not call this until api is initialized (ymaps API expects DOM element)
		}, this);
	},

	_update: function () {
		var map = this._map;
		var center = map.getCenter();
		this._yandex.setCenter([center.lat, center.lng], map.getZoom());
		var offset = L.point(0,0).subtract(L.DomUtil.getPosition(map.getPane('mapPane')));
		L.DomUtil.setPosition(this._container, offset); // move to visible part of pane
	},

	_resyncView: function () { // for use in addons
		if (!this._map) { return; }
		var ymap = this._yandex;
		this._map.setView(ymap.getCenter(), ymap.getZoom(), {animate: false});
	},

	_animateZoom: function (e) {
		var map = this._map;
		var viewHalf = map.getSize()._divideBy(2);
		var topLeft = map.project(e.center, e.zoom)._subtract(viewHalf)._round();
                var offset = map.project(map.getBounds().getNorthWest(), e.zoom)._subtract(topLeft);
		var scale = map.getZoomScale(e.zoom);
		this._animatedElements.length = 0;
		this._yandex.panes._array.forEach(function (el) {
			if (el.pane instanceof ymaps.pane.MovablePane) {
				var element = el.pane.getElement();
				L.DomUtil.addClass(element, 'leaflet-zoom-animated');
				L.DomUtil.setTransform(element, offset, scale);
				this._animatedElements.push(element);
			}
		},this);
	},

	_animateZoomEnd: function () {
		this._animatedElements.forEach(function (el) {
			L.DomUtil.setTransform(el, 0, 1);
		});
		this._animatedElements.length = 0;
	},

	_initApi: function () { // to be extended in addons
		ymaps.ready(this._initMapObject, this);
	},

	_mapType: function () {
		var shortType = this.options.type;
		if (!shortType || shortType.indexOf('#') !== -1) {
			return shortType;
		}
		return 'yandex#' + shortType;
	},

	_initMapObject: function () {
		ymaps.mapType.storage.add('yandex#overlay', new ymaps.MapType('overlay', []));
		ymaps.mapType.storage.add('yandex#skeleton', new ymaps.MapType('skeleton', ['yandex#skeleton']));
		ymaps.mapType.storage.add('yandex#map~vector', new ymaps.MapType('map~vector', ['yandex#map~vector']));
		var ymap = new ymaps.Map(this._container, {
			center: [0, 0], zoom: 0, behaviors: [], controls: [],
			type: this._mapType()
		}, this.options.mapOptions);

		if (this._isOverlay) {
			ymap.container.getElement().style.background = 'transparent';
		}
		this._container.remove();
		this._yandex = ymap;
		if (this._map) { this.onAdd(this._map); }

		this.fire('load');
	}
});

L.yandex = function (type, options) {
	return new L.Yandex(type, options);
};
<|endoftext|>


<commit_before>var sreq = require('sync-request');

// process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Allow StuGov server's SSL cert (most don't need this)
var key = process.env["bridgeapi_key"]; // Your API Private Key
var andrew = process.env["bridgeapi_andrew"]; // Your API Andrew ID
var url = "https://stugov.andrew.cmu.edu/staging/bridgeapi/api/v1/events";

exports.index = function(req, res) {
  // Get our Bridge API data
  var page = req.query.page || 1; // Either get page # from request or default
  var items = [];
  var options = { headers: { andrew_id: andrew, api_key: key }, qs: { "type": "public", "page": page } }; // Set our api request header options

  var api_res = sreq("POST", url, options); // Make a synchronous request
  if (api_res.statusCode !== 200) // Log error if something goes wrong
    console.log("Error! API returned with a status code of " + api_res.statusCode + ".");

  var data = JSON.parse(api_res.body) // Parse out our response
  items = items.concat(data.items.filter(function(e) { return e.flyerUrl && e.flyerUrl !== "" })); // Filter out only events with flyer images

  // Respond with only the partial if it's an AJAX request
  res.render('home', { layout: !req.xhr, items: items})
}
<commit_msg>Reject unauthorized set to false<commit_after>var sreq = require('sync-request');

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Allow StuGov server's SSL cert (most don't need this)
var key = process.env["bridgeapi_key"]; // Your API Private Key
var andrew = process.env["bridgeapi_andrew"]; // Your API Andrew ID
var url = "https://stugov.andrew.cmu.edu/staging/bridgeapi/api/v1/events";

exports.index = function(req, res) {
  // Get our Bridge API data
  var page = req.query.page || 1; // Either get page # from request or default
  var items = [];
  var options = { headers: { andrew_id: andrew, api_key: key }, qs: { "type": "public", "page": page } }; // Set our api request header options

  var api_res = sreq("POST", url, options); // Make a synchronous request
  if (api_res.statusCode !== 200) // Log error if something goes wrong
    console.log("Error! API returned with a status code of " + api_res.statusCode + ".");

  var data = JSON.parse(api_res.body) // Parse out our response
  items = items.concat(data.items.filter(function(e) { return e.flyerUrl && e.flyerUrl !== "" })); // Filter out only events with flyer images

  // Respond with only the partial if it's an AJAX request
  res.render('home', { layout: !req.xhr, items: items})
}
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { Markdown } from 'meteor/perak:markdown';
import { bootstrapAttachementsLiveQuery } from '/imports/collections/attachments_private';
import '/imports/config/accounts';

// initialize
//  * twitter bootstrap
//  * bootstrap-datetimepicker
//  * bootstrap-material-design

// with arrive we need exactly one $.material.init()
import 'arrive';

// required by bootstrap-datetimepicker
import 'moment/moment';

// bootstrap js
import 'bootstrap/dist/js/bootstrap';
import 'bootstrap/js/transition';
import 'bootstrap/js/collapse'

// bootstrap datetime picker
import 'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css';
import 'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min';

// material design
import 'bootstrap-material-design';
import 'bootstrap-material-design/dist/js/material';
import 'bootstrap-material-design/dist/js/ripples';

// jquery ui - use the download builder to select packages to load
// https://jqueryui.com/download/#!version=1.12.0&components=000000000000000000000000000000000000000000000000
// currently used:
//   * sortable (plus dependencies)
import 'jquery-ui/ui/widget';
import 'jquery-ui/ui/data';
import 'jquery-ui/ui/scroll-parent';
import 'jquery-ui/ui/widgets/mouse';
import 'jquery-ui/ui/widgets/sortable';

import 'jquery-ui-touch-punch/jquery.ui.touch-punch';

$(document).arrive('input', {
    onceOnly: false
}, function () {
    let invalidMsg = $(this).attr('data-error-msg');
    if(invalidMsg) {
        $(this).on('invalid', function() {
            this.setCustomValidity(invalidMsg);
        });
        $(this).on('input', function() {
            this.setCustomValidity('');
        });
    }
});

// as soon as the document is loaded initialize material design
$(document).ready(() => {
    $.material.init();
});

Meteor.startup(() => {
    Meteor.call("gitVersionInfoUpdate");

    bootstrapAttachementsLiveQuery();

    // Make sure that all server side markdown rendering quotes all HTML <TAGs>
    Markdown.setOptions({
        sanitize: true
    });

    Template.registerHelper("pathForImproved", function(path) {
        // FlowRouters pathFor helper is a little bit inconsistent.
        // for ROOT_URL=http://localhost:3000           it processes "/" => "/"
        // for ROOT_URL=http://localhost:3100/4minitz   it processes "/" => "/4minitz"
        // so sometimes we have a trailing "/" sometimes not.
        // Unfortunately serving an image like so " does not work!
        let pathWithTrailingSlash = Blaze._globalHelpers.pathFor(path);
        if (! pathWithTrailingSlash.endsWith("/")) {
            pathWithTrailingSlash = pathWithTrailingSlash + "/";
        }
        return pathWithTrailingSlash;
    });
});

window.onbeforeunload = function (e) {
    if(Meteor.status().connected) {
        e.cancel();
    }
    const message = "Do you really want to leave 4Minitz?",
        e = e || window.event;
    // For IE and Firefox
    if (e) {
        e.returnValue = message;
    }

    // For Safari
    return message;
};
<commit_msg>Improved event usage<commit_after>import { Meteor } from 'meteor/meteor';
import { Markdown } from 'meteor/perak:markdown';
import { bootstrapAttachementsLiveQuery } from '/imports/collections/attachments_private';
import '/imports/config/accounts';

// initialize
//  * twitter bootstrap
//  * bootstrap-datetimepicker
//  * bootstrap-material-design

// with arrive we need exactly one $.material.init()
import 'arrive';

// required by bootstrap-datetimepicker
import 'moment/moment';

// bootstrap js
import 'bootstrap/dist/js/bootstrap';
import 'bootstrap/js/transition';
import 'bootstrap/js/collapse'

// bootstrap datetime picker
import 'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css';
import 'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min';

// material design
import 'bootstrap-material-design';
import 'bootstrap-material-design/dist/js/material';
import 'bootstrap-material-design/dist/js/ripples';

// jquery ui - use the download builder to select packages to load
// https://jqueryui.com/download/#!version=1.12.0&components=000000000000000000000000000000000000000000000000
// currently used:
//   * sortable (plus dependencies)
import 'jquery-ui/ui/widget';
import 'jquery-ui/ui/data';
import 'jquery-ui/ui/scroll-parent';
import 'jquery-ui/ui/widgets/mouse';
import 'jquery-ui/ui/widgets/sortable';

import 'jquery-ui-touch-punch/jquery.ui.touch-punch';

$(document).arrive('input', {
    onceOnly: false
}, function () {
    let invalidMsg = $(this).attr('data-error-msg');
    if(invalidMsg) {
        $(this).on('invalid', function() {
            this.setCustomValidity(invalidMsg);
        });
        $(this).on('input', function() {
            this.setCustomValidity('');
        });
    }
});

// as soon as the document is loaded initialize material design
$(document).ready(() => {
    $.material.init();
});

Meteor.startup(() => {
    Meteor.call("gitVersionInfoUpdate");

    bootstrapAttachementsLiveQuery();

    // Make sure that all server side markdown rendering quotes all HTML <TAGs>
    Markdown.setOptions({
        sanitize: true
    });

    Template.registerHelper("pathForImproved", function(path) {
        // FlowRouters pathFor helper is a little bit inconsistent.
        // for ROOT_URL=http://localhost:3000           it processes "/" => "/"
        // for ROOT_URL=http://localhost:3100/4minitz   it processes "/" => "/4minitz"
        // so sometimes we have a trailing "/" sometimes not.
        // Unfortunately serving an image like so " does not work!
        let pathWithTrailingSlash = Blaze._globalHelpers.pathFor(path);
        if (! pathWithTrailingSlash.endsWith("/")) {
            pathWithTrailingSlash = pathWithTrailingSlash + "/";
        }
        return pathWithTrailingSlash;
    });
});

window.onbeforeunload = function (e) {
    let event = e || window.event;

    if(Meteor.status().connected) {
        event.cancel();
    }

    const message = "Do you really want to leave 4Minitz?";
    // For IE and Firefox
    if (event) {
        event.returnValue = message;
    }
    // For Safari
    return message;
};
<|endoftext|>


<commit_before>/* global goog, lime, obacht */
/* jshint strict: false, devel:true */

goog.provide('obacht.Game');

// Closure Library Requirements
goog.require('goog.pubsub.PubSub');

// Obacht Requirements
goog.require('obacht.World');
goog.require('obacht.Player');
goog.require('obacht.themes');

/**
 * Its a Game scene
 *
 * @constructor
 * @extends lime.Scene
 */
obacht.Game = function() {
    console.log('New Game();');

    //////////////////////////////
    // Game Model (state)       //
    //////////////////////////////

    this.ownWorld = new obacht.World('own');
    this.enemyWorld = new obacht.World('enemy');
    this.sky = new lime.Sprite().setSize(obacht.options.graphics.VIEWPORT_WIDTH, obacht.options.graphics.VIEWPORT_HEIGHT).setFill(obacht.themes.path.sky).setPosition(0, 0).setAnchorPoint(0, 0);

    this.ownPlayer = new obacht.Player('own');
    this.enemyPlayer = new obacht.Player('enemy');

    this.layer = new lime.Layer();
    this.layer.appendChild(this.sky);
    this.layer.appendChild(this.enemyWorld.layer);
    this.layer.appendChild(this.ownWorld.layer);
    this.layer.appendChild(this.enemyPlayer.layer);
    this.layer.appendChild(this.ownPlayer.layer);
    this.layer.appendChild(obacht.playerController.layer);

};

obacht.Game.prototype = {

};
<commit_msg>Bugfix<commit_after>/* global goog, lime, obacht */
/* jshint strict: false, devel:true */

goog.provide('obacht.Game');

// Closure Library Requirements
goog.require('goog.pubsub.PubSub');

// Obacht Requirements
goog.require('obacht.World');
goog.require('obacht.Player');
goog.require('obacht.themes');

/**
 * Its a Game scene
 *
 * @constructor
 * @extends lime.Scene
 */
obacht.Game = function() {
    console.log('New Game();');

    //////////////////////////////
    // Game Model (state)       //
    //////////////////////////////

    this.ownWorld = new obacht.World('own');
    this.enemyWorld = new obacht.World('enemy');
    this.sky = new lime.Sprite().setSize(obacht.options.graphics.VIEWPORT_WIDTH, obacht.options.graphics.VIEWPORT_HEIGHT).setFill(obacht.themes.path.sky).setPosition(0, 0).setAnchorPoint(0, 0);

    this.ownPlayer = new obacht.Player('own');
    this.enemyPlayer = new obacht.Player('enemy');

    this.layer = new lime.Layer();
    this.layer.appendChild(this.sky);
    this.layer.appendChild(this.enemyWorld.layer);
    this.layer.appendChild(this.ownWorld.layer);
    this.layer.appendChild(this.enemyPlayer.layer);
    this.layer.appendChild(this.ownPlayer.layer);
    this.layer.appendChild(obacht.playerController.layer);

    this.Generator=new obacht.Generator();
};

obacht.Game.prototype = {

};
<|endoftext|>


<commit_before>import Error from 'next/error'
import { withStyles } from '@material-ui/core/styles'
import Typography from '@material-ui/core/Typography'
import Layout from 'client/components/Layout'
import { getPhoto } from 'client/src/api'

const headerHeight = 64
const captionHeight = 20

const styles = theme => ({
  container: {
    textAlign: 'center',
  },
  caption: {
    marginTop: 4,
  },
  image: {
    position: 'relative',
    left: '50%',
    transform: 'translateX(-50%)',
  },
})

const ceiling = (num, ceiling) => (num > ceiling) ? ceiling : num

const byRatio = (initial, ratio) => Math.round(initial * ratio)

class Photo extends React.Component {
  constructor(props) {
    super(props)
    this.image = React.createRef()
    this.state = {
      maxWidth: undefined,
      maxHeight: undefined,
    }
  }

  static async getInitialProps({ query }) {
    if (!query.slug) return { error: true }
    if (!query.filename) return { error: true }

    const res = await getPhoto(query.slug, query.filename)
    return res
  }

  componentDidMount() {
    const element = this.image.current
    if (element && element.complete) {
        this.imageLoaded()
    }
  }

  imageLoaded = _event => {
    this.setState({
      maxWidth: global.innerWidth,
      maxHeight: global.innerHeight - headerHeight - captionHeight,
    })
  }

  calculateImageDimensions() {
    const { maxWidth } = this.state
    const imageElement = this.image.current
    if (!maxWidth || !imageElement) return undefined

    if (this.heightRatio() > this.widthRatio()) {
      return {
        width: byRatio(imageElement.width, this.widthRatio()),
        height: byRatio(imageElement.height, this.widthRatio()),
      }
    }
    return {
      width: byRatio(imageElement.width, this.heightRatio()),
      height: byRatio(imageElement.height, this.heightRatio()),
    }
  }

  heightRatio() {
    return ceiling(this.state.maxHeight / this.image.current.height, 1)
  }

  widthRatio() {
    return ceiling(this.state.maxWidth / this.image.current.width, 1)
  }

  render() {
    const { classes, user, photo, error } = this.props

    if (error) {
      return <Error statusCode={500} />
    }

    return (
      <Layout user={user} pageContext={this.props.pageContext}>

          <Typography className={classes.caption} variant="caption" color="inherit">
            {photo.caption}
          </Typography>

      </Layout>
    )
  }
}

export default withStyles(styles)(Photo)
<commit_msg>Resize photo on window resize<commit_after>import Error from 'next/error'
import { withStyles } from '@material-ui/core/styles'
import Typography from '@material-ui/core/Typography'
import Layout from 'client/components/Layout'
import { getPhoto } from 'client/src/api'
import debounce from 'lodash/debounce'

const headerHeight = 64
const captionHeight = 20

const styles = theme => ({
  container: {
    textAlign: 'center',
  },
  caption: {
    marginTop: 4,
  },
  image: {
    position: 'relative',
    left: '50%',
    transform: 'translateX(-50%)',
  },
})

const ceiling = (num, ceiling) => (num > ceiling) ? ceiling : num

const byRatio = (initial, ratio) => Math.round(initial * ratio)

const maxWidth = () => global.innerWidth

const maxHeight = () => global.innerHeight - headerHeight - captionHeight

class Photo extends React.Component {
  constructor(props) {
    super(props)
    this.image = React.createRef()
    this.state = {
      imageWidth: undefined,
      imageHeight: undefined,
    }
  }

  static async getInitialProps({ query }) {
    if (!query.slug) return { error: true }
    if (!query.filename) return { error: true }

    const res = await getPhoto(query.slug, query.filename)
    return res
  }

  componentDidMount() {
    window.addEventListener(
      'resize',
      debounce(() => this.forceUpdate(), 20, false),
      false)

    const element = this.image.current
    if (element && element.complete) {
        this.imageLoaded()
    }
  }

  imageLoaded = _event => {
    this.setState({
      imageWidth: this.image.current.width,
      imageHeight: this.image.current.height,
    })
  }

  calculateImageDimensions() {
    const { imageWidth, imageHeight } = this.state
    if (!imageWidth) return undefined

    if (this.heightRatio() > this.widthRatio()) {
      return {
        width: byRatio(imageWidth, this.widthRatio()),
        height: byRatio(imageHeight, this.widthRatio()),
      }
    }
    return {
      width: byRatio(imageWidth, this.heightRatio()),
      height: byRatio(imageHeight, this.heightRatio()),
    }
  }

  heightRatio() {
    return ceiling(maxHeight() / this.state.imageHeight, 1)
  }

  widthRatio() {
    return ceiling(maxWidth() / this.state.imageWidth, 1)
  }

  render() {
    const { classes, user, photo, error } = this.props

    if (error) {
      return <Error statusCode={500} />
    }

    return (
      <Layout user={user} pageContext={this.props.pageContext}>

          <Typography className={classes.caption} variant="caption" color="inherit">
            {photo.caption}
          </Typography>

      </Layout>
    )
  }
}

export default withStyles(styles)(Photo)
<|endoftext|>


<commit_before>// monkeypatch React for fixing https://github.com/facebook/react/issues/2461
// based on https://gist.github.com/Aldredcz/4d63b0a9049b00f54439f8780be7f0d8

import React from 'react'

let patched = false

export default (handleError = () => {}) => {
  if (patched) {
    throw new Error('React is already monkeypatched')
  }

  patched = true

  const { createElement } = React

  React.createElement = function (Component, ...rest) {
    if (typeof Component === 'function') {
      const { prototype } = Component

      // assumes it's a class component if render method exists.
      const isClassComponent = Boolean(prototype && prototype.render) ||
        // subclass of React.Component or PureComponent with no render method.
        // There's no render method in prototype
        // when it's created with class-properties.
        prototype instanceof React.Component ||
        prototype instanceof React.PureComponent

      if (isClassComponent) {
        if (prototype.render) {
          prototype.render = wrapRender(prototype.render)
        }

        // wrap the render method in runtime when the component initialized
        // for class-properties.
        Component = wrap(Component, withWrapOwnRender)
      } else {
        // stateless component
        Component = wrapRender(Component)
      }
    }

    return createElement.call(this, Component, ...rest)
  }

  const { Component: { prototype: componentPrototype } } = React
  const { forceUpdate } = componentPrototype

  componentPrototype.forceUpdate = function (...args) {
    if (this.render) {
      this.render = wrapRender(this.render)
    }
    return forceUpdate.apply(this, args)
  }

  function wrapRender (render) {
    return wrap(render, withHandleError)
  }

  function withHandleError (fn, ...args) {
    try {
      return fn.apply(this, args)
    } catch (err) {
      handleError(err)
      return null
    }
  }

  function withWrapOwnRender (fn, ...args) {
    const result = fn.apply(this, args)
    if (this.render && this.hasOwnProperty('render')) {
      this.render = wrapRender(this.render)
    }
    return result
  }
}

function wrap (fn, around) {
  if (fn.__wrapped) {
    return fn.__wrapped
  }

  const _fn = function (...args) {
    return around.call(this, fn, ...args)
  }

  // copy all properties
  Object.assign(_fn, fn)

  _fn.prototype = fn.prototype

  _fn.__wrapped = fn.__wrapped = _fn

  return _fn
}
<commit_msg>Do not patch prototypes with render exposed only as a getter. (#898)<commit_after>// monkeypatch React for fixing https://github.com/facebook/react/issues/2461
// based on https://gist.github.com/Aldredcz/4d63b0a9049b00f54439f8780be7f0d8

import React from 'react'

let patched = false

export default (handleError = () => {}) => {
  if (patched) {
    throw new Error('React is already monkeypatched')
  }

  patched = true

  const { createElement } = React

  React.createElement = function (Component, ...rest) {
    if (typeof Component === 'function') {
      // We need to get the prototype which has the render method.
      // It's possible to have render inside a deeper prototype due to
      // class extending.
      const prototypeWithRender = getRenderPrototype(Component)
      const { prototype } = Component

      // assumes it's a class component if render method exists.
      const isClassComponent = Boolean(prototypeWithRender) ||
        // subclass of React.Component or PureComponent with no render method.
        // There's no render method in prototype
        // when it's created with class-properties.
        prototype instanceof React.Component ||
        prototype instanceof React.PureComponent

      let dynamicWrapper = withWrapOwnRender

      if (isClassComponent) {
        if (prototypeWithRender) {
          // Sometimes render method is created with only a getter.
          // In that case we can't override it with a prototype. We need to
          // do it dynamically.
          if (canOverrideRender(prototypeWithRender)) {
            prototypeWithRender.render = wrapRender(prototypeWithRender.render)
          } else {
            dynamicWrapper = withWrapRenderAlways
          }
        }

        // wrap the render method in runtime when the component initialized
        // for class-properties.
        Component = wrap(Component, dynamicWrapper)
      } else {
        // stateless component
        Component = wrapRender(Component)
      }
    }

    return createElement.call(this, Component, ...rest)
  }

  const { Component: { prototype: componentPrototype } } = React
  const { forceUpdate } = componentPrototype

  componentPrototype.forceUpdate = function (...args) {
    if (this.render) {
      this.render = wrapRender(this.render)
    }
    return forceUpdate.apply(this, args)
  }

  function wrapRender (render) {
    return wrap(render, withHandleError)
  }

  function withHandleError (fn, ...args) {
    try {
      return fn.apply(this, args)
    } catch (err) {
      handleError(err)
      return null
    }
  }

  function withWrapOwnRender (fn, ...args) {
    const result = fn.apply(this, args)
    if (this.render && this.hasOwnProperty('render')) {
      this.render = wrapRender(this.render)
    }
    return result
  }

  function withWrapRenderAlways (fn, ...args) {
    const result = fn.apply(this, args)
    if (this.render) {
      this.render = wrapRender(this.render)
    }
    return result
  }
}

function wrap (fn, around) {
  if (fn.__wrapped) {
    return fn.__wrapped
  }

  const _fn = function (...args) {
    return around.call(this, fn, ...args)
  }

  // copy all properties
  Object.assign(_fn, fn)

  _fn.prototype = fn.prototype

  _fn.__wrapped = fn.__wrapped = _fn

  return _fn
}

function getRenderPrototype (Component) {
  let proto = Component.prototype

  while (true) {
    if (proto.hasOwnProperty('render')) return proto
    proto = Object.getPrototypeOf(proto)
    if (!proto) return null
  }
}

function canOverrideRender (prototype) {
  const descriptor = Object.getOwnPropertyDescriptor(prototype, 'render')
  if (!descriptor) return true

  return descriptor.writable
}
<|endoftext|>


<commit_before>var React = require('react');
import {
  Button,
  Grid,
  Row,
  Col,
  Image,
  Thumbnail
} from 'react-bootstrap';

var Home = React.createClass({
  render: function() {

    let movies = [
      {
        name: "The Pfellowship of the Ring",
        description: "A meek Quadling and seven companions set out on a journey to destroy the One Ring and the Dark Lord Adams.",
        image: "pfellowship-of-the-ring.png"
      }, {
        name: "Pfinding Nemo",
        description: "After his son is captured in the Charles River Reef and taken to Mather House, a timid clownfish sets out on a journey to bring him Pfohome.",
        image: "pfinding-nemo.png"
      }, {
        name: "Pforrest Gump",
        description: "Pforrest Gump, while not intelligent, has accidentally been present at many historic moments, but his true love, Pfoho, eludes him.",
        image: "pforrest-gump.png"
      }, {
        name: "Skypfall",
        description: "Bond's loyalty to PF is tested when her past comes back to haunt her. Whilst PfI6 comes under attack, 007 must track down and destroy the threat, no matter how personal the cost.",
        image: "skypfall.png"
      }, {
        name: "Star Wars: The Pforz Awakens",
        description: "Three decades after the defeat of the Quadrangle Empire, a new threat arises. The River Order attempts to rule the College and only a ragtag group of heroes can stop them, along with the help of the Pfresistance.",
        image: "the-pforz-awakens.png"
      }, {
        name: "Back to the Pfuture",
        description: "A young man is accidentally sent thirty years into the past in a time-traveling Quad Shuttle invented by his friend, Dr. Carl Pforzheimer, and must make sure his college-age parents unite in order to save his own existence.",
        image: "back-to-the-pfuture.png"
      }, {
        name: "Pfrozen",
        description: "When the newly crowned Queen Elsa accidentally uses her power to turn things into ice to curse the Quad in infinite winter, her sister, Anna, teams up with a Pfoho man, his playful polar bear, and a snowman to change the weather condition.",
        image: "pfrozen.jpg"
      }
    ];

    let movieImages = movies.map(movie => {
      let movieImage = `img/posters/${movie.image}`;
      return <Col key={movie.name} xs={6} md={3}>

        <Thumbnail src={movieImage} alt={movie.name} className="movie-poster">

{movie.name}

{movie.description}

        </Thumbnail>
      </Col>;
    });

    return (

Popular on Netpflix

        <Grid>
          <Row>
            {movieImages}
          </Row>
        </Grid>

    );
  }
});

module.exports = Home;
<commit_msg>Separate videos by category<commit_after>var React = require('react');
import {
  Button,
  Grid,
  Row,
  Col,
  Image,
  Thumbnail
} from 'react-bootstrap';

var Home = React.createClass({
  /**
     * Creates a poster element for a movie containing its image, name,
     * 	description, etc.
     * @param  {Object} movie
     * @return {<Col>}       a React element
     */
  posterForMovie: function(movie) {
    let movieImage = `img/posters/${movie.image}`;
    return <Col key={movie.name} xs={6} md={3}>
      <Thumbnail src={movieImage} alt={movie.name} className="movie-poster">

{movie.name}

{movie.description}

      </Thumbnail>
    </Col>;
  },

  render: function() {

    // Different states of movies: recently watched, currently popular, new
    // arrivals, etc.
    const categories = {
      POPULAR: "popular",
      RECENT: "recent",
      NEW_ARRIVAL: "new"
    };

    let movies = [
      {
        name: "The Pfellowship of the Ring",
        description: `A meek Quadling and seven companions set out on a journey to destroy the
            One Ring and the Dark Lord Adams.`,
        category: categories.POPULAR,
        image: "pfellowship-of-the-ring.png"
      }, {
        name: "Pfinding Nemo",
        description: `After his son is captured in the Charles River Reef and taken to Mather House, a
            timid clownfish sets out on a journey to bring him Pfohome.`,
        category: categories.POPULAR,
        image: "pfinding-nemo.png"
      }, {
        name: "Pforrest Gump",
        description: `Pforrest Gump, while not intelligent, has accidentally been present at many
            historic moments, but his true love, Pfoho, eludes him.`,
        category: categories.POPULAR,
        image: "pforrest-gump.png"
      }, {
        name: "Skypfall",
        description: `Bond's loyalty to PF is tested when her past comes back to haunt her. Whilst
            PfI6 comes under attack, 007 must track down and destroy the threat, no matter how
            personal the cost.`,
        category: categories.POPULAR,
        image: "skypfall.png"
      }, {
        name: "Star Wars: The Pforz Awakens",
        description: `Three decades after the defeat of the Quadrangle Empire, a new threat arises. The
            River Order attempts to rule the College and only a ragtag group of heroes can stop them,
            along with the help of the Pfresistance.`,
        category: categories.NEW_ARRIVAL,
        image: "the-pforz-awakens.png"
      }, {
        name: "Back to the Pfuture",
        description: `A young man is accidentally sent thirty years into the past in a time-traveling
            Quad Shuttle invented by his friend, Dr. Carl Pforzheimer, and must make sure his
            college-age parents unite in order to save his own existence.`,
        category: categories.POPULAR,
        image: "back-to-the-pfuture.png"
      }, {
        name: "Pfrozen",
        description: `When the newly crowned Queen Elsa accidentally uses her power to turn things into
            ice to curse the Quad in infinite winter, her sister, Anna, teams up with a Pf
            oho man, his playful polar bear, and a snowman to change the weather condition.`,
        category: categories.RECENT,
        image: "pfrozen.jpg",
        video: "https://www.youtube.com/watch?v=uKPrkR1wkfA"
      }
    ];

    /**
     * Given a list of movies and a category, reutrns posters of movies in
     * that category.
     */
    let postersByCategory = (movies, category) => movies
      .filter(movie => movie.category == category)
      .map(this.posterForMovie);

    let posters = {
      popular: postersByCategory(movies, categories.POPULAR),
      recent: postersByCategory(movies, categories.RECENT),
      newArrivals: postersByCategory(movies, categories.NEW_ARRIVAL)
    };

    let wrapInGrid = (posters) => <Grid>
      <Row>
        {posters}
      </Row>
    </Grid>;

    return (

New Arrivals

        {wrapInGrid(posters.newArrivals)}

Popular on Netpflix

        {wrapInGrid(posters.popular)}

Recently Viewed

        {wrapInGrid(posters.recent)}

    );
  }
});

module.exports = Home;
<|endoftext|>


<commit_before>/*
This component is the map view. It shows the user the possible routes he/she can take to arrive at the destination
*/

var React = require('react');
var RouteDetailView = require('./routeDetailView')
var ListView = require('./listView')

var MapView = React.createClass({
  // adds access to the router context. the getCurrentParams method can then be used to get the properties from the route
  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState () {
    return {
      routes: [],
      currentRoute: null,
      routingBoxes: []
    }
  },

  // this is called after the first reder of the component
  componentDidMount () {
    var {origin, destination} = this.context.router.getCurrentParams();

    var start = this.getLatLong(origin);
    var end = this.getLatLong(destination);

    var map = this.initializeMap(start);
    this.setState({
      map: map
    });
    this.calcRoute(start, end, map);
  },

  // turns a lat/long string into a google maps LatLong Object
  getLatLong (location) {
    return new google.maps.LatLng(location.split(',')[0], location.split(',')[1]);
  },

  // initializes a map and attaches it to the map div
  initializeMap (center) {
    var mapOptions = {
      zoom: 10,
      center,
    };
    return new google.maps.Map(document.getElementById('map'), mapOptions);
  },

  // set the current selected route
  setCurrentRoute (index) {
    // clear previously active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions(this.defaultOptions);
    }

    this.setState({
      currentRoute: this.state.routes[index]
    });

    // update new routeingBoxes
    this.updateRoutingBoxes();
  },

  defaultOptions: {
    zIndex: 1,
    strokeOpacity: 0.4,
    strokeWeight: 4
  },

  // this creates a directions route from the start point to the end point
  calcRoute (start, end, map) {
    var directionsService = new google.maps.DirectionsService();
    var component = this;

    // create markers
    new google.maps.Marker({
      position: start,
      map,
      label: 'A'
    });
    new google.maps.Marker({
      position: end,
      map,
      label: 'B'
    });

    var request = {
      origin:start,
      destination:end,
      travelMode: google.maps.TravelMode.DRIVING,
      provideRouteAlternatives: true,
    }; //request

    // make a directios request to the maps API
    directionsService.route(request, function (response, status) {
      if (status == google.maps.DirectionsStatus.OK) { //.OK indicates the response contains a valid DirectionsResult.
        console.log(response);
        var routes = [];
        var colors = ['blue', 'red', 'green'];

        // default polyline options

        for (var i = 0, len = response.routes.length; i < len; i++) {
          // create a polyline for each suggested route
          var polyLine = new google.maps.Polyline({
            path: response.routes[i].overview_path,
            strokeColor: colors[i],
            map
          });

          // add properties to each polyline
          polyLine.path = response.routes[i].overview_path;
          polyLine.color = colors[i];
          polyLine.distance = response.routes[i].legs[0].distance.text;
          polyLine.duration = response.routes[i].legs[0].duration.text;

          polyLine.setOptions(component.defaultOptions);
          // save polylines for later use
          routes.push(polyLine);

          // on the initial load make the first suggestion active
          if (i === 0) {
            component.setState({
              currentRoute: polyLine,
              // currentPath: response.routes[i].overview_path //test
            });
          } //if

          // add event listener to update the route on click
          polyLine.addListener('click', component.setCurrentRoute.bind(component, i));

        } //for(each route)

        component.setState({
          routes
        });

        /**** Routing Box ****/
        component.updateRoutingBoxes();
      } // if
    }); //directionsService.route callback
  }, //calcRoutes()
  updateRoutingBoxes () {
    // get routing box info from good api
    console.log("TEST inside updateRoutingBoxes() currentRoute = ", this.state.currentRoute.path);

    var routeBoxer = new RouteBoxer();
    var distance = 5; // km

    var routingBoxes = routeBoxer.box(this.state.currentRoute.path, distance);
    this.setState({
      routingBoxes
    });

    console.log("ROUTINGBOX", routingBoxes)
    // this.drawBoxes(boxes);

  },
  // // Draw the array of boxes as polylines on the map
  // drawBoxes (boxes) {
  //   var boxpolys = [];

  //   for (var i = 0; i < boxes.length; i++) {
  //     boxpolys.push(new google.maps.Rectangle({
  //       bounds: boxes[i],
  //       fillOpacity: 0,
  //       strokeOpacity: 1.0,
  //       strokeColor: '#000000',
  //       strokeWeight: 1,
  //       map: this.state.map
  //     }));
  //   } //for

  // }, // drawBoxes()

  // // Clear boxes currently on the map
  // clearBoxes () {
  //   if (boxpolys != null) {
  //     for (var i = 0; i < boxpolys.length; i++) {
  //       boxpolys[i].setMap(null);
  //     }
  //   }
  //   boxpolys = null;
  // }, // clearBoxes()

  render () {
    // update display of active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions({
        zIndex: 2,
        strokeOpacity: 1,
      });
    };

    return (

        Welcome to the MapView!

        <RouteDetailView
          routes={this.state.routes}
          setCurrentRoute={this.setCurrentRoute} />
        <ListView routingBoxes={this.state.routingBoxes} />

    )
  }
});

module.exports = MapView;
<commit_msg>Change from routingBoxes to evenly spaced points on the road<commit_after>/*
This component is the map view. It shows the user the possible routes he/she can take to arrive at the destination
*/

var React = require('react');
var RouteDetailView = require('./routeDetailView')
var ListView = require('./listView')

var MapView = React.createClass({
  // adds access to the router context. the getCurrentParams method can then be used to get the properties from the route
  contextTypes: {
    router: React.PropTypes.func
  },

  getInitialState () {
    return {
      routes: [],
      currentRoute: null,
      routingBoxes: [],
      wayPoints: []
    }
  },

  // this is called after the first reder of the component
  componentDidMount () {
    var {origin, destination} = this.context.router.getCurrentParams();

    var start = this.getLatLong(origin);
    var end = this.getLatLong(destination);

    var map = this.initializeMap(start);
    this.setState({
      map: map
    });
    this.calcRoute(start, end, map);
  },

  // turns a lat/long string into a google maps LatLong Object
  getLatLong (location) {
    return new google.maps.LatLng(location.split(',')[0], location.split(',')[1]);
  },

  // initializes a map and attaches it to the map div
  initializeMap (center) {
    var mapOptions = {
      zoom: 10,
      center,
    };
    return new google.maps.Map(document.getElementById('map'), mapOptions);
  },

  // set the current selected route
  setCurrentRoute (index) {
    // clear previously active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions(this.defaultOptions);
    }

    this.setState({
      currentRoute: this.state.routes[index]
    });

    // update new wayPoints
    this.getWayPoints();
  },

  defaultOptions: {
    zIndex: 1,
    strokeOpacity: 0.4,
    strokeWeight: 4
  },

  // this creates a directions route from the start point to the end point
  calcRoute (start, end, map) {
    var directionsService = new google.maps.DirectionsService();
    var component = this;

    // create markers
    new google.maps.Marker({
      position: start,
      map,
      label: 'A'
    });
    new google.maps.Marker({
      position: end,
      map,
      label: 'B'
    });

    var request = {
      origin:start,
      destination:end,
      travelMode: google.maps.TravelMode.DRIVING,
      provideRouteAlternatives: true,
    }; //request

    // make a directios request to the maps API
    directionsService.route(request, function (response, status) {
      if (status == google.maps.DirectionsStatus.OK) { //.OK indicates the response contains a valid DirectionsResult.
        console.log(response);
        var routes = [];
        var colors = ['blue', 'red', 'green'];

        for (var i = 0, len = response.routes.length; i < len; i++) {
          // create a polyline for each suggested route
          var polyLine = new google.maps.Polyline({
            path: response.routes[i].overview_path,
            strokeColor: colors[i],
            map
          });

          // add properties to each polyline
          polyLine.path = response.routes[i].overview_path;
          polyLine.color = colors[i];
          polyLine.distance = response.routes[i].legs[0].distance.text;
          polyLine.duration = response.routes[i].legs[0].duration.text;

          polyLine.setOptions(component.defaultOptions);
          // save polylines for later use
          routes.push(polyLine);

          // on the initial load make the first suggestion active
          if (i === 0) {
            component.setState({
              currentRoute: polyLine,
              // currentPath: response.routes[i].overview_path //test
            });
          } //if

          // add event listener to update the route on click
          polyLine.addListener('click', component.setCurrentRoute.bind(component, i));

        } //for(each route)

        component.setState({
          routes
        });

        /**** Routing Box ****/
        component.getWayPoints();
      } // if
    }); //directionsService.route callback
  }, //calcRoutes()

  getWayPoints (map, radius) {

    radius = radius || 10;
    var path = this.state.currentRoute.path;
    var map = this.state.map;

    var wayPoints = [];
    var lastPoint;

    var getDistanceBetweenPoints = function(a, b) {
      var d = Math.sqrt(Math.pow(a.G-b.G, 2) + Math.pow(a.K-b.K, 2));
      return d * 110;
    }

    var getMiddlePoint = function(a, b) {
      return new google.maps.LatLng((a.G+b.G)/2, (a.K+b.K)/2);
    }

    path.forEach(function(point) {
      if (!lastPoint) {
        wayPoints.push(point);
        lastPoint = point;
      }
      // add an inbetween point if the distance is too big
      if (getDistanceBetweenPoints(lastPoint, point) > 1.5 * radius) {
        wayPoints.push(getMiddlePoint(lastPoint, point));
      }
      if (getDistanceBetweenPoints(lastPoint, point) > radius) {
        wayPoints.push(point);
        lastPoint = point;
      }
    });

    this.setState({
      wayPoints
    });

    // display points
    wayPoints.forEach(function(point) {
      new google.maps.Circle({
        center: point,
        map: map,
        radius: radius*1000,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35,
      });
    });

    console.log("wayPoints", wayPoints);
    console.log("Path", path);
  },

  render () {
    // update display of active route
    if (this.state.currentRoute) {
      this.state.currentRoute.setOptions({
        zIndex: 2,
        strokeOpacity: 1,
      });
    };

    return (

        Welcome to the MapView!

        <RouteDetailView
          routes={this.state.routes}
          setCurrentRoute={this.setCurrentRoute} />
        <ListView routingBoxes={this.state.wayPoints} />

    )
  }
});

module.exports = MapView;
<|endoftext|>