<commit_before>function platformLoad(task,platform,metaData) {
	platform.openUrl = function(sTextId, success, error) {success();};
	platform.updateHeight = function(height,success,error) {
      $('#taskIframe').height(height);
      success();
   };
   var getHeightInterval = window.setInterval(function() {
      task.getHeight(function(height) {
         $('#taskIframe').height(height);
      });
   }, 1000);
   var syncStateInterval = window.setInterval(function() {
      task.getState(function(state) {
         if (state == lastState) {
            return;
         }
         $.post('api-entry.php', {platformName: platformName, action: 'saveState', sToken: token, sState: state}, function(res) {
            if (!res.success) {
               console.error('error in saving state');
               return;
            }
         }, 'json').fail(console.error);
      });
   }, 3000);

   var taskViews = {};
   var loadedViews = {'task': true, 'solution': true, 'hints': true, 'editor': true, 'grader': true, 'metadata': true, 'submission': true};
   var shownViews = {'task': true};
   var showViewsHandlerFactory = function (view) {
      return function() {
         var tmp = {};
         tmp[view] = true;
         task.showViews(tmp, function(){});
         $('.choose-view-button').removeClass('btn-info');
         if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
            $('#choose-view-top-'+view).addClass('btn-info');
         }
         if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
            $('#choose-view-bottom-'+view).addClass('btn-info');
         }
      };
   };
   var displayTabs = function() {
      $("#choose-view-top").html("");
      $("#choose-view-bottom").html("");
      for (var iView = 0; iView < viewOrder.length; iView++) {
         var viewName = viewOrder[iView];//taskViews
         if (!taskViews[viewName]) continue;
         if (!taskViews[viewName].requires && viewNames[viewName] && (viewName != 'solution' || bAccessSolution)) {
            if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
               $("#choose-view-top").append($('<button id="choose-view-top-'+viewName+'" class="btn btn-default choose-view-button">' + viewNames[viewName] + '</button>').click(showViewsHandlerFactory(viewName)));
            }
            if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
               $("#choose-view-bottom").append($('<button id="choose-view-bottom-'+viewName+'" class="btn btn-default choose-view-button">' + viewNames[viewName] + '</button>').click(showViewsHandlerFactory(viewName)));
            }
         }
      }
   };

	platform.getTaskParams = function(key, defaultValue, success, error) {
      var res = {'minScore': 0, 'maxScore': 100, 'noScore': 0, 'readOnly': false, 'randomSeed': 0, 'options': {}, returnUrl: returnUrl};
      if (key) {
         if (key !== 'options' && key in res) {
            res = res[key];
         } else if (res.options && key in res.options) {
            res = res.options[key];
         } else {
            res = (typeof defaultValue !== 'undefined') ? defaultValue : null;
         }
      }
      if (success) {
         success(res);
      } else {
         return res;
      }
   };
   platform.askHint = function(hintToken, success, error) {
      if (!usesTokens) {
         success();
         return;
      }
      $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'askHint', hintToken: hintToken}, function(postRes){
         if (postRes.success && postRes.token) {
            token = postRes.token;
         	task.updateToken(token, function() {
         		success();
         	}, error);
         } else {
         	error('error in api-entry.php: '+postRes.error);
         }
      }, 'json').fail(error);
   };

   function showSolution() {
      bAccessSolution = true;
      displayTabs();
   }

   function gradeCurrentAnswer(success,error) {
      if (usesTokens) {
   		task.getAnswer(function (answer) {
            $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'getAnswerToken', sToken: token, sAnswer: answer}, function(postRes){
               if (postRes.success && postRes.token) {
                  task.gradeAnswer(answer, postRes.token, function(score,message,scoreToken) {
                     $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'graderReturn', score: score, message: message, scoreToken: scoreToken}, {responseType: 'json'}).success(function(postRes) {
                        if (postRes.success) {
                           success();
                           if (postRes.token) {
                              task.updateToken(postRes.token, function() {});
                              showSolution();
                           }
                        } else {
                           error('something went wrong with api-entry.php: '+postRes.error);
                        }
                     }, 'json').fail(error);
                  }, error);
               } else {
                  error('error in api-entry.php: '+postRes.error);
               }
            }, 'json').fail(error);
         }, error);
      } else {
         task.getAnswer(function (answer) {
            task.gradeAnswer(answer, null, function(score,message) {
               $.post('api-entry.php', {platformName: platformName, action: 'graderReturnNoToken', score: score, message: message, sToken: token, sAnswer: answer}, {responseType: 'json'}).success(function(postRes) {
                  if (postRes.success) {
                     success();
                     if (postRes.token) {
                        task.updateToken(postRes.token, function() {});
                        showSolution();
                     }
                  } else {
                     error('something went wrong with api-entry.php: '+postRes.error);
                  }
               }, 'json').fail(error);
            }, error);
         }, error);
      }
   }
	platform.validate = function(mode, success, error) {
	   if (mode == 'cancel') {
	      task.reloadAnswer('', success, error);
	      return;
	   } else {
      	gradeCurrentAnswer(success,error);
	   }
	};

   task.load(loadedViews, function() {
      task.getViews(function(views){
         taskViews = views;
         displayTabs();
      });
      task.showViews(shownViews, function() {
         $('.choose-view-button').removeClass('btn-info');
         $.each(shownViews, function(viewName) {
            if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
               $('#choose-view-top-'+viewName).addClass('btn-info');
            }
            if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
               $('#choose-view-bottom-'+viewName).addClass('btn-info');
            }
         });
      });
      task.reloadAnswer(lastAnswer, function() {});
      if (lastState) {
         task.reloadState(lastState, function() {});
      }
   });
}

function init() {
	TaskProxyManager.getTaskProxy('taskIframe', function(task) {
		var platform = new Platform(task);
		TaskProxyManager.setPlatform(task, platform);
		task.getMetaData(function(metaData) {
         platformLoad(task, platform, metaData);
     	});
  	}, true);
}

$(document).ready(function() {
	init();
});<commit_msg>reloadAnswer after reloadState<commit_after>function platformLoad(task,platform,metaData) {
	platform.openUrl = function(sTextId, success, error) {success();};
	platform.updateHeight = function(height,success,error) {
      $('#taskIframe').height(height);
      success();
   };
   var getHeightInterval = window.setInterval(function() {
      task.getHeight(function(height) {
         $('#taskIframe').height(height);
      });
   }, 1000);
   var syncStateInterval = window.setInterval(function() {
      task.getState(function(state) {
         if (state == lastState) {
            return;
         }
         $.post('api-entry.php', {platformName: platformName, action: 'saveState', sToken: token, sState: state}, function(res) {
            if (!res.success) {
               console.error('error in saving state');
               return;
            }
         }, 'json').fail(console.error);
      });
   }, 3000);

   var taskViews = {};
   var loadedViews = {'task': true, 'solution': true, 'hints': true, 'editor': true, 'grader': true, 'metadata': true, 'submission': true};
   var shownViews = {'task': true};
   var showViewsHandlerFactory = function (view) {
      return function() {
         var tmp = {};
         tmp[view] = true;
         task.showViews(tmp, function(){});
         $('.choose-view-button').removeClass('btn-info');
         if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
            $('#choose-view-top-'+view).addClass('btn-info');
         }
         if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
            $('#choose-view-bottom-'+view).addClass('btn-info');
         }
      };
   };
   var displayTabs = function() {
      $("#choose-view-top").html("");
      $("#choose-view-bottom").html("");
      for (var iView = 0; iView < viewOrder.length; iView++) {
         var viewName = viewOrder[iView];//taskViews
         if (!taskViews[viewName]) continue;
         if (!taskViews[viewName].requires && viewNames[viewName] && (viewName != 'solution' || bAccessSolution)) {
            if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
               $("#choose-view-top").append($('<button id="choose-view-top-'+viewName+'" class="btn btn-default choose-view-button">' + viewNames[viewName] + '</button>').click(showViewsHandlerFactory(viewName)));
            }
            if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
               $("#choose-view-bottom").append($('<button id="choose-view-bottom-'+viewName+'" class="btn btn-default choose-view-button">' + viewNames[viewName] + '</button>').click(showViewsHandlerFactory(viewName)));
            }
         }
      }
   };

	platform.getTaskParams = function(key, defaultValue, success, error) {
      var res = {'minScore': 0, 'maxScore': 100, 'noScore': 0, 'readOnly': false, 'randomSeed': 0, 'options': {}, returnUrl: returnUrl};
      if (key) {
         if (key !== 'options' && key in res) {
            res = res[key];
         } else if (res.options && key in res.options) {
            res = res.options[key];
         } else {
            res = (typeof defaultValue !== 'undefined') ? defaultValue : null;
         }
      }
      if (success) {
         success(res);
      } else {
         return res;
      }
   };
   platform.askHint = function(hintToken, success, error) {
      if (!usesTokens) {
         success();
         return;
      }
      $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'askHint', hintToken: hintToken}, function(postRes){
         if (postRes.success && postRes.token) {
            token = postRes.token;
         	task.updateToken(token, function() {
         		success();
         	}, error);
         } else {
         	error('error in api-entry.php: '+postRes.error);
         }
      }, 'json').fail(error);
   };

   function showSolution() {
      bAccessSolution = true;
      displayTabs();
   }

   function gradeCurrentAnswer(success,error) {
      if (usesTokens) {
   		task.getAnswer(function (answer) {
            $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'getAnswerToken', sToken: token, sAnswer: answer}, function(postRes){
               if (postRes.success && postRes.token) {
                  task.gradeAnswer(answer, postRes.token, function(score,message,scoreToken) {
                     $.post('api-entry.php', {taskPlatformName: taskPlatformName, action: 'graderReturn', score: score, message: message, scoreToken: scoreToken}, {responseType: 'json'}).success(function(postRes) {
                        if (postRes.success) {
                           success();
                           if (postRes.token) {
                              task.updateToken(postRes.token, function() {});
                              showSolution();
                           }
                        } else {
                           error('something went wrong with api-entry.php: '+postRes.error);
                        }
                     }, 'json').fail(error);
                  }, error);
               } else {
                  error('error in api-entry.php: '+postRes.error);
               }
            }, 'json').fail(error);
         }, error);
      } else {
         task.getAnswer(function (answer) {
            task.gradeAnswer(answer, null, function(score,message) {
               $.post('api-entry.php', {platformName: platformName, action: 'graderReturnNoToken', score: score, message: message, sToken: token, sAnswer: answer}, {responseType: 'json'}).success(function(postRes) {
                  if (postRes.success) {
                     success();
                     if (postRes.token) {
                        task.updateToken(postRes.token, function() {});
                        showSolution();
                     }
                  } else {
                     error('something went wrong with api-entry.php: '+postRes.error);
                  }
               }, 'json').fail(error);
            }, error);
         }, error);
      }
   }
	platform.validate = function(mode, success, error) {
	   if (mode == 'cancel') {
	      task.reloadAnswer('', success, error);
	      return;
	   } else {
      	gradeCurrentAnswer(success,error);
	   }
	};

   task.load(loadedViews, function() {
      task.getViews(function(views){
         taskViews = views;
         displayTabs();
      });
      task.showViews(shownViews, function() {
         $('.choose-view-button').removeClass('btn-info');
         $.each(shownViews, function(viewName) {
            if (buttonsPosition == 'top' || buttonsPosition == 'topbottom') {
               $('#choose-view-top-'+viewName).addClass('btn-info');
            }
            if (buttonsPosition == 'bottom' || buttonsPosition == 'topbottom') {
               $('#choose-view-bottom-'+viewName).addClass('btn-info');
            }
         });
      });
      if (lastState) {
         task.reloadState(lastState, function() {});
      }
      task.reloadAnswer(lastAnswer, function() {});
   });
}

function init() {
	TaskProxyManager.getTaskProxy('taskIframe', function(task) {
		var platform = new Platform(task);
		TaskProxyManager.setPlatform(task, platform);
		task.getMetaData(function(metaData) {
         platformLoad(task, platform, metaData);
     	});
  	}, true);
}

$(document).ready(function() {
	init();
});
<|endoftext|>


<commit_before>var dashboard = require('./mock-dashboard.js');
var wadi = require('./wadi.js');

var express = require('express');
var expressHandlebars  = require('express-handlebars');

// go find all the activity for wadi repo's

var gRepositories = [
  { user: 'mozilla', repo: 'oghliner' },
  { user: 'mozilla', repo: 'platatus' },
  { user: 'mozilla', repo: 'serviceworker-cookbook' },
  { user: 'mozilla', repo: 'progressive-apps-hq' },
  { user: 'mozilla', repo: 'wp-web-push' },
  { user: 'marco-c', repo: 'web-push' },
  { user: 'marco-c', repo: 'mercurius' },
  { user: 'darkwing', repo: 'wp-sw-cache' },
  { user: 'owencm', repo: 'ModernWebSummitWorkshop' },
];

wadi.setDashboard(dashboard);

function trackWADIRepositories() {
  gRepositories.forEach(function (r) {
      wadi.addEventsFromRepo(r.user, r.repo);
  });
}

wadi.addBugsTrackedBy(1201717); // web app developer initiative tracker
wadi.addBugsTrackedBy(1059784); // Ship Service Workers on desktop on the release channel
wadi.addBugsTrackedBy(1207262); // Ship Service Workers on Android on the release channel
wadi.addBugsTrackedBy(1003097); // Worker debugging
wadi.addBugsTrackedBy(1156054); // Implement Push API on Android
wadi.addBugsTrackedBy(1201571); // Tracking bug for Push Notifications

gHomeScreenStats = {};

wadi.npmDownloads('oghliner', gHomeScreenStats);

gRepositories.forEach(function(r) {
  wadi.getStargazers(r.user, r.repo, 1, gHomeScreenStats);
});

trackWADIRepositories();
setInterval(trackWADIRepositories, 300000);

var server = express();

server.engine('handlebars', expressHandlebars({
  defaultLayout: 'main',
  helpers: {
    truncate : function(inString, inLength) {
      if (inString) {
        return inString.substring(0, inLength);
      } else {
        return inString;
      }
    },
    activityType : function (inActivity) {
      return inActivity.type;
    },
    historyType : function (inHistory) {
      return inHistory.field_name;
    },
    somebodyAssigned: function (assignee) {
      return (assignee != 'nobody@mozilla.org');
    },
    recent: function (dateField) {
      var when = new Date(dateField);
      var days = (new Date() - when) / (24*60*60*1000);
      return days < 7;
    },
    stringify: function (json) {
      return JSON.stringify(json);
    }
  }
}));

server.set('view engine', 'handlebars');

server.use('/lib', express.static('lib'));
server.use('/fonts', express.static('fonts'));

server.get('/home', function (req, res) {
    console.log(JSON.stringify(gHomeScreenStats));
    res.render('home', {stats: gHomeScreenStats});
});

server.get('/bugs', function (req, res) {
  var bugDictionary = wadi.getAllBugInfo();
  var keys = Object.getOwnPropertyNames(bugDictionary);
  var bugArray = keys.map(function (k) { return bugDictionary[k]; });
  var sortedBugs = bugArray.sort(function(x, y) {
    if (x.latest < y.latest) {
      return 1;
    } else if (x.latest > y.latest) {
      return -1;
    } else {
      return 0;
    }
  });

  res.render('bugs', {bugs: sortedBugs});
});

server.get('/events', function (req, res) {
  var events = wadi.getAllEvents();
  var keys = Object.getOwnPropertyNames(wadi.getAllEvents());

  keys.sort();
  keys.reverse();

  var sortedEvents = keys.map(function (k) { return events[k]; } );

  res.render('events', {events: sortedEvents});
});

server.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});<commit_msg>add one more repo<commit_after>var dashboard = require('./mock-dashboard.js');
var wadi = require('./wadi.js');

var express = require('express');
var expressHandlebars  = require('express-handlebars');

// go find all the activity for wadi repo's

var gRepositories = [
  { user: 'mozilla', repo: 'oghliner' },
  { user: 'mozilla', repo: 'platatus' },
  { user: 'mozilla', repo: 'serviceworker-cookbook' },
  { user: 'mozilla', repo: 'progressive-apps-hq' },
  { user: 'mozilla', repo: 'wp-web-push' },
  { user: 'mozilla', repo: 'wp-add-to-homescreen' },
  { user: 'marco-c', repo: 'web-push' },
  { user: 'marco-c', repo: 'mercurius' },
  { user: 'darkwing', repo: 'wp-sw-cache' },
  { user: 'owencm', repo: 'ModernWebSummitWorkshop' },
];

wadi.setDashboard(dashboard);

function trackWADIRepositories() {
  gRepositories.forEach(function (r) {
      wadi.addEventsFromRepo(r.user, r.repo);
  });
}

wadi.addBugsTrackedBy(1201717); // web app developer initiative tracker
wadi.addBugsTrackedBy(1059784); // Ship Service Workers on desktop on the release channel
wadi.addBugsTrackedBy(1207262); // Ship Service Workers on Android on the release channel
wadi.addBugsTrackedBy(1003097); // Worker debugging
wadi.addBugsTrackedBy(1156054); // Implement Push API on Android
wadi.addBugsTrackedBy(1201571); // Tracking bug for Push Notifications

gHomeScreenStats = {};

wadi.npmDownloads('oghliner', gHomeScreenStats);

gRepositories.forEach(function(r) {
  wadi.getStargazers(r.user, r.repo, 1, gHomeScreenStats);
});

trackWADIRepositories();
setInterval(trackWADIRepositories, 300000);

var server = express();

server.engine('handlebars', expressHandlebars({
  defaultLayout: 'main',
  helpers: {
    truncate : function(inString, inLength) {
      if (inString) {
        return inString.substring(0, inLength);
      } else {
        return inString;
      }
    },
    activityType : function (inActivity) {
      return inActivity.type;
    },
    historyType : function (inHistory) {
      return inHistory.field_name;
    },
    somebodyAssigned: function (assignee) {
      return (assignee != 'nobody@mozilla.org');
    },
    recent: function (dateField) {
      var when = new Date(dateField);
      var days = (new Date() - when) / (24*60*60*1000);
      return days < 7;
    },
    stringify: function (json) {
      return JSON.stringify(json);
    }
  }
}));

server.set('view engine', 'handlebars');

server.use('/lib', express.static('lib'));
server.use('/fonts', express.static('fonts'));

server.get('/home', function (req, res) {
    console.log(JSON.stringify(gHomeScreenStats));
    res.render('home', {stats: gHomeScreenStats});
});

server.get('/bugs', function (req, res) {
  var bugDictionary = wadi.getAllBugInfo();
  var keys = Object.getOwnPropertyNames(bugDictionary);
  var bugArray = keys.map(function (k) { return bugDictionary[k]; });
  var sortedBugs = bugArray.sort(function(x, y) {
    if (x.latest < y.latest) {
      return 1;
    } else if (x.latest > y.latest) {
      return -1;
    } else {
      return 0;
    }
  });

  res.render('bugs', {bugs: sortedBugs});
});

server.get('/events', function (req, res) {
  var events = wadi.getAllEvents();
  var keys = Object.getOwnPropertyNames(wadi.getAllEvents());

  keys.sort();
  keys.reverse();

  var sortedEvents = keys.map(function (k) { return events[k]; } );

  res.render('events', {events: sortedEvents});
});

server.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});<|endoftext|>


<commit_before>(function($) {
	$.entwine('ss', function($) {
		$('.ss-gridfield .gridfield-sortablerows input').entwine({
			PageSort: false,

			onmatch: function() {
				var self=this;
				var refCheckbox=$(this);
				var gridField=this.getGridField();
				var form=gridField.closest('form');
				var pageArrows=gridField.find('.gridfield-sortablerows-movepage .sortablerows-psort-arrow');

				if($(this).is(':checked')) {
					gridField.find('table').addClass('dragSorting');
				}else {
					gridField.find('table').removeClass('dragSorting');
				}

				gridField.find('tbody').sortable({
												opacity: 0.6,
												disabled: ($(this).is(':checked')==false),
												helper: function(e, ui) {
													//Maintains width of the columns
													ui.children().each(function(index) {
														$(this).width($(this).width());
													});

													return ui;
												},
												start: function(event, ui) {
													pageArrows.show();
													pageArrows.redraw();
													pageArrows.startMoveTracking();
												},
												stop: function(event, ui) {
													pageArrows.stopMoveTracking();
													pageArrows.hide();
												},
												sort: function(event, ui) {
													pageArrows.moveTracking(event, ui);
												},
												update: function(event, ui) {
													if(self.getPageSort()) {
														self.setPageSort(false);
														return;
													}

													var gridItems=gridField.getItems();

													gridItems.removeClass('first last odd even');
													gridItems.first().addClass('first');
													gridItems.last().addClass('last');
													gridItems.filter(':even').addClass('odd');
													gridItems.filter(':odd').addClass('even');

													var dataRows=[];
													var button=refCheckbox.parent().find('.sortablerows-savesort');

													for(var i=0;i<gridItems.length;i++) {
														dataRows[i]=$(gridItems[i]).data('id');
													}

													self._makeRequest({data: [
																				{
																					name: button.attr('name'),
																					value: button.val()
																				},
																				{
																					name: 'ItemIDs',
																					value: dataRows
																				}
																			]},function() {
																				form.removeClass('loading');
																			});
												}
											}).disableSelection();
			},

			onchange: function(e) {
				var gridField=this.getGridField();
				gridField.find('tbody').sortable('option', 'disabled', ($(this).is(':checked')==false));
				gridField.setState('GridFieldSortableRows', {sortableToggle: $(this).is(':checked')});

				var button=$(this).parent().find('.sortablerows-toggle');
				gridField.reload({data: [{name: button.attr('name'), value: button.val()}]});
			},

			_makeRequest: function(ajaxOpts, callback) {
				var gridField=this.getGridField();
				var form = gridField.closest('form');

				form.addClass('loading');

				ajaxOpts.data = ajaxOpts.data.concat(form.find(':input').serializeArray());

				// Include any GET parameters from the current URL, as the view state might depend on it.
				// For example, a list prefiltered through external search criteria might be passed to GridField.
				if(window.location.search) {
					ajaxOpts.data = window.location.search.replace(/^\?/, '') + '&' + $.param(ajaxOpts.data);
				}

				$.ajax($.extend({}, {
					headers: {"X-Pjax" : 'CurrentField'},
					type: "POST",
					url: gridField.data('url'),
					dataType: 'html',
					success: callback,
					error: function(e) {
						alert(ss.i18n._t('GRIDFIELD.ERRORINTRANSACTION'));
					}
				}, ajaxOpts));
			}
		});

		$('.ss-gridfield .gridfield-sortablerows-movepage .sortablerows-psort-arrow').entwine({
			ArrowIcon: null,

			onmatch: function() {
				var gridField=this.getGridField();
				var sortableCheckbox=gridField.find('.gridfield-sortablerows input');
				var self=$(this);

				if($(this).hasClass('sortablerows-prev-page') && gridField.find('.ss-gridfield-previouspage').is(':disabled')) {
					$(this).remove();
					return;
				}else if($(this).hasClass('sortablerows-next-page') && gridField.find('.ss-gridfield-nextpage').is(':disabled')) {
					$(this).remove();
					return;
				}

				$(this).droppable({
									disabled: $(this).is(':disabled'),
									accept: 'tr.ss-gridfield-item',
									activeClass: 'sortablerows-droptarget',
									tolerance: 'pointer',
									drop: function(event, ui) {
										self.stopMoveTracking();

										sortableCheckbox.setPageSort(true);
										sortableCheckbox.setPageArrows(null);

										var button=gridField.find('.gridfield-sortablerows .sortablerows-sorttopage');
										var itemID=$(ui.draggable).data('id');
										var target='';

										if($(this).hasClass('sortablerows-prev-page')) {
											target='previouspage';
										}else if($(this).hasClass('sortablerows-next-page')) {
											target='nextpage';
										}

										//Move and Reload the grid
										gridField.reload({data: [
																	{
																		name: button.attr('name'),
																		value: button.val()
																	},
																	{
																		name: 'ItemID',
																		value: itemID
																	},
																	{
																		name: 'Target',
																		value: target
																	}
																]});
									}
								});

				this.redraw();
			},
			redraw: function() {
				var gridField=this.getGridField();
				var tbody=gridField.find('tbody');
				var tbodyPos=tbody.position();

				$(this).css('top', tbodyPos.top+'px').height(tbody.height());
			},
			startMoveTracking: function() {
				var self=$(this);
				self.setArrowIcon(self.find('i'));
			},
			stopMoveTracking: function() {
				$(this).setArrowIcon(null);
			},
			moveTracking: function(e, ui) {
				var self=$(this);
				var arrowIcon=self.getArrowIcon();
				if(arrowIcon) {
					var selfOffset=self.offset().top;
					var arrowIconHeight=arrowIcon.width()+10;
					var railHeight=self.height()-arrowIconHeight;
					var helperPos=ui.helper.offset().top;

					if(helperPos>selfOffset+10 && helperPos<selfOffset+railHeight) {
						arrowIcon.css('top', ((helperPos-selfOffset)+arrowIconHeight/2)+'px');
					}
				}
			}
		});
	});

})(jQuery);<commit_msg>Fixed error when dropping onto the arrows<commit_after>(function($) {
	$.entwine('ss', function($) {
		$('.ss-gridfield .gridfield-sortablerows input').entwine({
			PageSort: false,

			onmatch: function() {
				var self=this;
				var refCheckbox=$(this);
				var gridField=this.getGridField();
				var form=gridField.closest('form');
				var pageArrows=gridField.find('.gridfield-sortablerows-movepage .sortablerows-psort-arrow');

				if($(this).is(':checked')) {
					gridField.find('table').addClass('dragSorting');
				}else {
					gridField.find('table').removeClass('dragSorting');
				}

				gridField.find('tbody').sortable({
												opacity: 0.6,
												disabled: ($(this).is(':checked')==false),
												helper: function(e, ui) {
													//Maintains width of the columns
													ui.children().each(function(index) {
														$(this).width($(this).width());
													});

													return ui;
												},
												start: function(event, ui) {
													pageArrows.show();
													pageArrows.redraw();
													pageArrows.startMoveTracking();
												},
												stop: function(event, ui) {
													pageArrows.stopMoveTracking();
													pageArrows.hide();
												},
												sort: function(event, ui) {
													pageArrows.moveTracking(event, ui);
												},
												update: function(event, ui) {
													if(self.getPageSort()) {
														self.setPageSort(false);
														return;
													}

													var gridItems=gridField.getItems();

													gridItems.removeClass('first last odd even');
													gridItems.first().addClass('first');
													gridItems.last().addClass('last');
													gridItems.filter(':even').addClass('odd');
													gridItems.filter(':odd').addClass('even');

													var dataRows=[];
													var button=refCheckbox.parent().find('.sortablerows-savesort');

													for(var i=0;i<gridItems.length;i++) {
														dataRows[i]=$(gridItems[i]).data('id');
													}

													self._makeRequest({data: [
																				{
																					name: button.attr('name'),
																					value: button.val()
																				},
																				{
																					name: 'ItemIDs',
																					value: dataRows
																				}
																			]},function() {
																				form.removeClass('loading');
																			});
												}
											}).disableSelection();
			},

			onchange: function(e) {
				var gridField=this.getGridField();
				gridField.find('tbody').sortable('option', 'disabled', ($(this).is(':checked')==false));
				gridField.setState('GridFieldSortableRows', {sortableToggle: $(this).is(':checked')});

				var button=$(this).parent().find('.sortablerows-toggle');
				gridField.reload({data: [{name: button.attr('name'), value: button.val()}]});
			},

			_makeRequest: function(ajaxOpts, callback) {
				var gridField=this.getGridField();
				var form = gridField.closest('form');

				form.addClass('loading');

				ajaxOpts.data = ajaxOpts.data.concat(form.find(':input').serializeArray());

				// Include any GET parameters from the current URL, as the view state might depend on it.
				// For example, a list prefiltered through external search criteria might be passed to GridField.
				if(window.location.search) {
					ajaxOpts.data = window.location.search.replace(/^\?/, '') + '&' + $.param(ajaxOpts.data);
				}

				$.ajax($.extend({}, {
					headers: {"X-Pjax" : 'CurrentField'},
					type: "POST",
					url: gridField.data('url'),
					dataType: 'html',
					success: callback,
					error: function(e) {
						alert(ss.i18n._t('GRIDFIELD.ERRORINTRANSACTION'));
					}
				}, ajaxOpts));
			}
		});

		$('.ss-gridfield .gridfield-sortablerows-movepage .sortablerows-psort-arrow').entwine({
			ArrowIcon: null,

			onmatch: function() {
				var gridField=this.getGridField();
				var sortableCheckbox=gridField.find('.gridfield-sortablerows input');
				var self=$(this);

				if($(this).hasClass('sortablerows-prev-page') && gridField.find('.ss-gridfield-previouspage').is(':disabled')) {
					$(this).remove();
					return;
				}else if($(this).hasClass('sortablerows-next-page') && gridField.find('.ss-gridfield-nextpage').is(':disabled')) {
					$(this).remove();
					return;
				}

				$(this).droppable({
									disabled: $(this).is(':disabled'),
									accept: 'tr.ss-gridfield-item',
									activeClass: 'sortablerows-droptarget',
									tolerance: 'pointer',
									drop: function(event, ui) {
										self.stopMoveTracking();

										sortableCheckbox.setPageSort(true);

										var button=gridField.find('.gridfield-sortablerows .sortablerows-sorttopage');
										var itemID=$(ui.draggable).data('id');
										var target='';

										if($(this).hasClass('sortablerows-prev-page')) {
											target='previouspage';
										}else if($(this).hasClass('sortablerows-next-page')) {
											target='nextpage';
										}

										//Move and Reload the grid
										gridField.reload({data: [
																	{
																		name: button.attr('name'),
																		value: button.val()
																	},
																	{
																		name: 'ItemID',
																		value: itemID
																	},
																	{
																		name: 'Target',
																		value: target
																	}
																]});
									}
								});

				this.redraw();
			},
			redraw: function() {
				var gridField=this.getGridField();
				var tbody=gridField.find('tbody');
				var tbodyPos=tbody.position();

				$(this).css('top', tbodyPos.top+'px').height(tbody.height());
			},
			startMoveTracking: function() {
				var self=$(this);
				self.setArrowIcon(self.find('i'));
			},
			stopMoveTracking: function() {
				$(this).setArrowIcon(null);
			},
			moveTracking: function(e, ui) {
				var self=$(this);
				var arrowIcon=self.getArrowIcon();
				if(arrowIcon) {
					var selfOffset=self.offset().top;
					var arrowIconHeight=arrowIcon.width()+10;
					var railHeight=self.height()-arrowIconHeight;
					var helperPos=ui.helper.offset().top;

					if(helperPos>selfOffset+10 && helperPos<selfOffset+railHeight) {
						arrowIcon.css('top', ((helperPos-selfOffset)+arrowIconHeight/2)+'px');
					}
				}
			}
		});
	});

})(jQuery);<|endoftext|>


<commit_before>serveAPI = function(limitSegment){
  var posts = [];
  var limit = 100; // default limit: 100 posts

  if(typeof limitSegment !== 'undefined')
    limit = limitSegment;

  Posts.find({status: STATUS_APPROVED}, {sort: {submitted: -1}, limit: limit}).forEach(function(post) {
    var url = (post.url ? post.url : getPostUrl(post._id));
    var properties = {
     headline: post.headline,
     author: post.author,
     date: post.submitted,
     url: url,
     guid: post._id
    };

    if(post.body)
      properties['body'] = post.body;

    if(post.url)
      properties['domain'] = getDomain(url);

    if(twitterName = getTwitterNameById(post.userId))
      properties['twitterName'] = twitterName;

    posts.push(properties);
  });

  return JSON.stringify(posts);
}<commit_msg> API에서 category가 isModerator인 것들은 제외.<commit_after>serveAPI = function(limitSegment){
  var posts = [];
  var limit = 100; // default limit: 100 posts

  if(typeof limitSegment !== 'undefined')
    limit = limitSegment;

  Posts.find({status: STATUS_APPROVED, categories:{$not:{$elemMatch:{isModerator:true}}}}, {sort: {submitted: -1}, limit: limit}).forEach(function(post) {
    var url = (post.url ? post.url : getPostUrl(post._id));
    var properties = {
     headline: post.headline,
     author: post.author,
     date: post.submitted,
     url: url,
     guid: post._id
    };

    if(post.body)
      properties['body'] = post.body;

    if(post.url)
      properties['domain'] = getDomain(url);

    if(twitterName = getTwitterNameById(post.userId))
      properties['twitterName'] = twitterName;

    posts.push(properties);
  });

  return JSON.stringify(posts);
}<|endoftext|>


<commit_before>/**
	A popup is used to display content that should be displayed on top of other
	content.

	Popups are initially hidden on creation; they can be shown by calling the
	_show_ method and re-hidden by calling _hide_.  Popups may be centered using
	the	_centered_ property; if not centered, they should be given a specific
	position.

	A popup may be optionally floated above all application content by setting
	its _floating_ property to true.  This has the advantage of guaranteeing
	that the popup will be displayed on top of other content.  This usage is
	appropriate when the popup does not need to scroll with other content.

	The _autoDismiss_ property controls how a popup may be dismissed.  If true
	(the default), then tapping outside the popup or pressing the ESC key will
	dismiss the popup.

	The _modal_ property may be set to true to prevent any
	controls outside the popup from responding to events while the popup is
	showing.

		{kind: "enyo.Popup", centered: true, modal: true, floating: true, components: [
			{content: "Here's some information..."}
		]}
 */
enyo.kind({
	name: "enyo.Popup",
	classes: "enyo-popup",
	published: {
		//* Set to true to prevent controls outside the popup from receiving events while the popup is showing.
		modal: false,
		//* By default, the popup will hide when the user taps outside it or presses ESC.  Set to false to prevent this behavior.
		autoDismiss: true,
		//* If true, the popup will be rendered in a floating layer outside of other controls.  This can be used to
		//* guarantee that the popup will be shown on top of other controls.
		floating: false,
		//* Set to true to automatically center the popup in the middle of the viewport.
		centered: false
	},
	//* @protected
	showing: false,
	handlers: {
		ondown: "down",
		onkeydown: "keydown",
		onfocus: "focus",
		onblur: "blur",
		onRequestShow: "requestShow",
		onRequestHide: "requestHide"
	},
	captureEvents: true,
	//* @public
	events: {
		//@ Event that fires after the popup is shown.
		onShow: "",
		//@ Event that fires after the popup is hidden.
		onHide: ""
	},
	//* @protected
	tools: [
		{kind: "Signals", onKeydown: "keydown"}
	],
	create: function() {
		this.inherited(arguments);
		if (this.floating) {
			this.setParent(enyo.floatingLayer);
		}
	},
	destroy: function() {
		if (this.showing) {
			this.release();
		}
		this.inherited(arguments);
	},
	// bubble events to owner when floating
	getBubbleTarget: function() {
		return this.floating ? this.owner : this.inherited(arguments);
	},
	reflow: function() {
		this.updatePosition();
		this.inherited(arguments);
	},
	calcViewportSize: function() {
		if (window.innerWidth) {
			return {
				width: window.innerWidth,
				height: window.innerHeight
			};
		} else {
			var e = document.documentElement;
			return {
				width: e.offsetWidth,
				height: e.offsetHeight
			};
		}
	},
	updatePosition: function() {
		if (this.centered) {
			var d = this.calcViewportSize();
			var b = this.getBounds();
			this.addStyles("top: " + ((d.height-b.height)/2) + "px; left: " + ((d.width-b.width)/2) + "px;");
		}
	},
	showingChanged: function() {
		// auto render when shown.
		if (this.floating && this.showing && !this.hasNode()) {
			this.render();
		}
		// hide while sizing
		if (this.centered) {
			this.applyStyle("visibility", "hidden");
		}
		this.inherited(arguments);
		if (this.showing) {
			this.resized();
			if (this.captureEvents) {
				this.capture();
			}
		} else {
			if (this.captureEvents) {
				this.release();
			}
		}
		// show after sizing
		if (this.centered) {
			this.applyStyle("visibility", null);
		}
		// events desired due to programmatic show/hide
		if (this.hasNode()) {
			this[this.showing ? "doShow" : "doHide"]();
		}
	},
	capture: function() {
		enyo.dispatcher.capture(this, !this.modal);
	},
	release: function() {
		enyo.dispatcher.release();
	},
	down: function(inSender, inEvent) {
		// prevent focus from shifting outside the popup when modal.
		if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) {
			inEvent.preventDefault();
		}
	},
	tap: function(inSender, inEvent) {
		// dismiss on tap if property is set and click was outside the popup
		if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this))) {
			this.hide();
			return true;
		}
	},
	keydown: function(inSender, inEvent) {
		if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) {
			this.hide();
		}
	},
	// if something inside the popup blurred, keep track of it
	blur: function(inSender, inEvent) {
		if (inEvent.dispatchTarget.isDescendantOf(this)) {
			this.lastFocus = inEvent.originator;
		}
	},
	// when something outside the popup focuses (e.g., due to tab key), focus our last focused control.
	focus: function(inSender, inEvent) {
		var dt = inEvent.dispa2tchTarget;
		if (this.modal && !dt.isDescendantOf(this)) {
			if (dt.hasNode()) {
				dt.node.blur();
			}
			var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode();
			if (n) {
				n.focus();
			}
		}
	},
	requestShow: function(inSender, inEvent) {
		this.show();
		return true;
	},
	requestHide: function(inSender, inEvent) {
		this.hide();
		return true;
	}
});
<commit_msg>Fix dispatchTarget in focus<commit_after>/**
	A popup is used to display content that should be displayed on top of other
	content.

	Popups are initially hidden on creation; they can be shown by calling the
	_show_ method and re-hidden by calling _hide_.  Popups may be centered using
	the	_centered_ property; if not centered, they should be given a specific
	position.

	A popup may be optionally floated above all application content by setting
	its _floating_ property to true.  This has the advantage of guaranteeing
	that the popup will be displayed on top of other content.  This usage is
	appropriate when the popup does not need to scroll with other content.

	The _autoDismiss_ property controls how a popup may be dismissed.  If true
	(the default), then tapping outside the popup or pressing the ESC key will
	dismiss the popup.

	The _modal_ property may be set to true to prevent any
	controls outside the popup from responding to events while the popup is
	showing.

		{kind: "enyo.Popup", centered: true, modal: true, floating: true, components: [
			{content: "Here's some information..."}
		]}
 */
enyo.kind({
	name: "enyo.Popup",
	classes: "enyo-popup",
	published: {
		//* Set to true to prevent controls outside the popup from receiving events while the popup is showing.
		modal: false,
		//* By default, the popup will hide when the user taps outside it or presses ESC.  Set to false to prevent this behavior.
		autoDismiss: true,
		//* If true, the popup will be rendered in a floating layer outside of other controls.  This can be used to
		//* guarantee that the popup will be shown on top of other controls.
		floating: false,
		//* Set to true to automatically center the popup in the middle of the viewport.
		centered: false
	},
	//* @protected
	showing: false,
	handlers: {
		ondown: "down",
		onkeydown: "keydown",
		onfocus: "focus",
		onblur: "blur",
		onRequestShow: "requestShow",
		onRequestHide: "requestHide"
	},
	captureEvents: true,
	//* @public
	events: {
		//@ Event that fires after the popup is shown.
		onShow: "",
		//@ Event that fires after the popup is hidden.
		onHide: ""
	},
	//* @protected
	tools: [
		{kind: "Signals", onKeydown: "keydown"}
	],
	create: function() {
		this.inherited(arguments);
		if (this.floating) {
			this.setParent(enyo.floatingLayer);
		}
	},
	destroy: function() {
		if (this.showing) {
			this.release();
		}
		this.inherited(arguments);
	},
	// bubble events to owner when floating
	getBubbleTarget: function() {
		return this.floating ? this.owner : this.inherited(arguments);
	},
	reflow: function() {
		this.updatePosition();
		this.inherited(arguments);
	},
	calcViewportSize: function() {
		if (window.innerWidth) {
			return {
				width: window.innerWidth,
				height: window.innerHeight
			};
		} else {
			var e = document.documentElement;
			return {
				width: e.offsetWidth,
				height: e.offsetHeight
			};
		}
	},
	updatePosition: function() {
		if (this.centered) {
			var d = this.calcViewportSize();
			var b = this.getBounds();
			this.addStyles("top: " + ((d.height-b.height)/2) + "px; left: " + ((d.width-b.width)/2) + "px;");
		}
	},
	showingChanged: function() {
		// auto render when shown.
		if (this.floating && this.showing && !this.hasNode()) {
			this.render();
		}
		// hide while sizing
		if (this.centered) {
			this.applyStyle("visibility", "hidden");
		}
		this.inherited(arguments);
		if (this.showing) {
			this.resized();
			if (this.captureEvents) {
				this.capture();
			}
		} else {
			if (this.captureEvents) {
				this.release();
			}
		}
		// show after sizing
		if (this.centered) {
			this.applyStyle("visibility", null);
		}
		// events desired due to programmatic show/hide
		if (this.hasNode()) {
			this[this.showing ? "doShow" : "doHide"]();
		}
	},
	capture: function() {
		enyo.dispatcher.capture(this, !this.modal);
	},
	release: function() {
		enyo.dispatcher.release();
	},
	down: function(inSender, inEvent) {
		// prevent focus from shifting outside the popup when modal.
		if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) {
			inEvent.preventDefault();
		}
	},
	tap: function(inSender, inEvent) {
		// dismiss on tap if property is set and click was outside the popup
		if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this))) {
			this.hide();
			return true;
		}
	},
	keydown: function(inSender, inEvent) {
		if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) {
			this.hide();
		}
	},
	// if something inside the popup blurred, keep track of it
	blur: function(inSender, inEvent) {
		if (inEvent.dispatchTarget.isDescendantOf(this)) {
			this.lastFocus = inEvent.originator;
		}
	},
	// when something outside the popup focuses (e.g., due to tab key), focus our last focused control.
	focus: function(inSender, inEvent) {
		var dt = inEvent.dispatchTarget;
		if (this.modal && !dt.isDescendantOf(this)) {
			if (dt.hasNode()) {
				dt.node.blur();
			}
			var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode();
			if (n) {
				n.focus();
			}
		}
	},
	requestShow: function(inSender, inEvent) {
		this.show();
		return true;
	},
	requestHide: function(inSender, inEvent) {
		this.hide();
		return true;
	}
});
<|endoftext|>


<commit_before>import path from 'path';
import express from 'express';
import bodyParser from 'body-parser';
import config from '../config';
import logger from './logger';
import apiRouter from './api-router';
import { notFound, logErrors, clientErrorHandler, errorHandler } from './error-handlers';
import { NotFoundException } from './exceptions';

// Set Winston console log level
logger.transports.console.level = config.logger.console.level;

// console.log === console.log in webpack.config
//eslint-disable-next-line no-console
console.log('express:',
  `NODE_ENV: "${process.env.NODE_ENV}",`,
  `isProd: ${config.isProd},`,
  `isDev: ${config.isDev},`,
  `isTest: ${config.isTest},`,
  `isHot: ${config.isHot},`,
  `loglevel: "${config.logger.console.level}",`,
  `public: "${config.server.publicPath}",`,
  `api: "${config.apiPath}"`);

let devMiddleware = null;

const app = express();
app.disable('x-powered-by');

// Middleware for handling JSON, Raw, Text and URL encoded form data
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

if (config.server.compress) {
  // compression middleware compresses your server responses which makes them
  // smaller (applies also to assets). You can read more about that technique
  // and other good practices on official Express.js docs http://mxs.is/googmy
  const compression = require('compression'); // eslint-disable-line global-require
  app.use(compression());
}

if (config.proxy) {
  // Proxy to api server
  const proxy = require('http-proxy-middleware'); // eslint-disable-line global-require

  const useProxy = (proxyConfig) => {
    app.use(proxy(proxyConfig.context, {
      ...proxyConfig.options,
      onProxyReq(req) {
        logger.info(`Proxy to: ${req.path}`);
      }
    }));
  };

  if (Array.isArray(config.proxy)) {
    config.proxy.forEach( p => {
      useProxy(p);
    });
  }
  else {
    useProxy(config.proxy);
  }
}
else {
  // Api routes
  app.use(config.apiPath, apiRouter);
}

// Uncomment to disable historyApiFallback without modifying config files
//config.server.historyApiFallback = false;

if (config.server.historyApiFallback) {
  // This rewrites all routes requests to the root /index.html file
  // (ignoring file requests). If you want to implement universal
  // rendering, you'll want to remove this middleware.
  const history = require('connect-history-api-fallback'); // eslint-disable-line global-require
  app.use(history(config.server.historyApiFallback));
}

if (config.isProd && !config.isTest) {
  app.use(config.server.publicPath, express.static(config.server.contentBase));

  app.get('*', (req, res, next) => {

    const reqPath = req.path.startsWith(config.server.publicPath)
      ? req.path.replace(config.server.publicPath, '')
      : req.path;

    const target = reqPath.indexOf('.') > -1
      ? path.join(config.server.contentBase, reqPath)
      : path.join(config.server.contentBase, 'index.html');

    logger.info('### app.get * from:', req.path, 'to:', target);

    res.sendFile(target, err => {
      if (err) {
        next(NotFoundException(req.path));
      }
    });
  });
}

if (config.isDev || config.isTest) {
  // Step 1: Create & configure a webpack compiler
  const webpack = require('webpack'); // eslint-disable-line global-require
  const webpackConfig = require('../webpack.config.babel'); // eslint-disable-line global-require
  const webpackCompiler = webpack(webpackConfig);
  webpackCompiler.apply(new webpack.ProgressPlugin());

  // Step 2: Attach the dev middleware to the compiler & the server
  // Config options:
  //   see: https://github.com/webpack/webpack-dev-middleware
  //   see: https://webpack.js.org/configuration/dev-server/
  //   see: https://webpack.js.org/configuration/stats/
  //   see: https://webpack.github.io/docs/webpack-dev-server.html
  //   see: https://github.com/chimurai/http-proxy-middleware
  //   see: https://github.com/bripkens/connect-history-api-fallback
  //   NOTE: Only use options compatible with webpack-dev-middleware
  const webpackDevMiddleware = require('webpack-dev-middleware'); // eslint-disable-line global-require

  devMiddleware = webpackDevMiddleware(webpackCompiler, {
    publicPath: webpackConfig.output.publicPath,
    stats: 'errors-only',
    /*
    stats: {
      errors: true,
      colors: true,
    },
    */
  });
  app.use(devMiddleware);

  // Step 3: Attach the hot middleware to the compiler & the server
  // Config options:
  //   See: https://github.com/glenjamin/webpack-hot-middleware
  if (config.isHot) {
    app.use(require('webpack-hot-middleware')(webpackCompiler));

    /*
    const webpackHotMiddleware = require('webpack-hot-middleware'); // eslint-disable-line global-require
    const hotMiddleware = webpackHotMiddleware(webpackCompiler, {
      path: '/__webpack_hmr'
      // You can use full urls, like:
      // path: `http://${host}:${port}${publicPath}/__webpack_hmr`
      // Remember to update webpack-hot-middleware in ../webpack-config.babel
    });
    app.use(hotMiddleware);
    */
  }

  // Add public path after step 3
  app.use(config.server.publicPath, express.static(config.server.contentBase));

  // Since webpackDevMiddleware uses memory-fs internally to store build
  // artifacts, we use it instead
  const memoryFs = devMiddleware.fileSystem;

  app.get('*', (req, res, next) => {

    const reqPath = req.path.startsWith(config.server.publicPath)
      ? req.path.replace(config.server.publicPath, '')
      : req.path;

    const target = reqPath.indexOf('.') > -1
      ? path.join(webpackCompiler.outputPath, reqPath)
      : path.join(webpackCompiler.outputPath, 'index.html');

    if (target.endsWith('.html')) {
      // 1: Read from memory fs
      logger.info('1 app.get * from:', req.path, 'to:', target);
      memoryFs.readFile(target, (err, file) => {
        if (err) {
          next(NotFoundException(req.path));
        } else {
          res.send(file.toString());
        }
      });
    }
    else {
      // 2: Try reading from outputPath, i.e. "dist"
      logger.info('2 app.get * from:', req.path, 'to:', target);
      res.sendFile(target, err => {
        if (err) {
          // 3: Try reading from src
          const src = path.join(config.server.contentBase, reqPath);
          logger.info('3 app.get * from:', req.path, 'to:', src);

          res.sendFile(src, err => {
            if (err) {
              next(NotFoundException(req.path));
            }
          });
        }
      });
    }
  });
}

// Catch 404 and forward to error handler
app.use(notFound);

// Error handlers
app.use(logErrors);          // Log errors
app.use(clientErrorHandler); // Client error handler
app.use(errorHandler);       // Catch all error handler

// See: https://nodejs.org/api/process.html#process_event_unhandledrejection
process.on('unhandledRejection', (reason, p) => {
  logger.error('Unhandled Rejection at:', p, 'reason:', reason);
});

// See: https://nodejs.org/api/process.html#process_event_uncaughtexception
process.on('uncaughtException', err => {
  logger.error('Server Uncaught Exception ', err);
  process.exit(1);
});

export default app;
export { devMiddleware };
<commit_msg>Corrected publicPath config<commit_after>import path from 'path';
import express from 'express';
import bodyParser from 'body-parser';
import config from '../config';
import logger from './logger';
import apiRouter from './api-router';
import { notFound, logErrors, clientErrorHandler, errorHandler } from './error-handlers';
import { NotFoundException } from './exceptions';

// Set Winston console log level
logger.transports.console.level = config.logger.console.level;

// console.log === console.log in webpack.config
//eslint-disable-next-line no-console
console.log('express:',
  `NODE_ENV: "${process.env.NODE_ENV}",`,
  `isProd: ${config.isProd},`,
  `isDev: ${config.isDev},`,
  `isTest: ${config.isTest},`,
  `isHot: ${config.isHot},`,
  `loglevel: "${config.logger.console.level}",`,
  `public: "${config.server.publicPath}",`,
  `api: "${config.apiPath}"`);

let devMiddleware = null;

const app = express();
app.disable('x-powered-by');

// Middleware for handling JSON, Raw, Text and URL encoded form data
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

if (config.server.compress) {
  // compression middleware compresses your server responses which makes them
  // smaller (applies also to assets). You can read more about that technique
  // and other good practices on official Express.js docs http://mxs.is/googmy
  const compression = require('compression'); // eslint-disable-line global-require
  app.use(compression());
}

if (config.proxy) {
  // Proxy to api server
  const proxy = require('http-proxy-middleware'); // eslint-disable-line global-require

  const useProxy = (proxyConfig) => {
    app.use(proxy(proxyConfig.context, {
      ...proxyConfig.options,
      onProxyReq(req) {
        logger.info(`Proxy to: ${req.path}`);
      }
    }));
  };

  if (Array.isArray(config.proxy)) {
    config.proxy.forEach( p => {
      useProxy(p);
    });
  }
  else {
    useProxy(config.proxy);
  }
}
else {
  // Api routes
  app.use(config.apiPath, apiRouter);
}

// Uncomment to disable historyApiFallback without modifying config files
//config.server.historyApiFallback = false;

if (config.server.historyApiFallback) {
  // This rewrites all routes requests to the root /index.html file
  // (ignoring file requests). If you want to implement universal
  // rendering, you'll want to remove this middleware.
  const history = require('connect-history-api-fallback'); // eslint-disable-line global-require
  app.use(history(config.server.historyApiFallback));
}

if (config.isProd && !config.isTest) {
  app.use(config.server.publicPath, express.static(config.server.contentBase));

  app.get('*', (req, res, next) => {

    const reqPath = req.path.startsWith(config.server.publicPath)
      ? req.path.replace(config.server.publicPath, '')
      : req.path;

    const target = reqPath.indexOf('.') > -1
      ? path.join(config.server.contentBase, reqPath)
      : path.join(config.server.contentBase, 'index.html');

    logger.info('### app.get * from:', req.path, 'to:', target);

    res.sendFile(target, err => {
      if (err) {
        next(NotFoundException(req.path));
      }
    });
  });
}

if (config.isDev || config.isTest) {
  // Step 1: Create & configure a webpack compiler
  const webpack = require('webpack'); // eslint-disable-line global-require
  const webpackConfig = require('../webpack.config.babel'); // eslint-disable-line global-require
  const webpackCompiler = webpack(webpackConfig);
  webpackCompiler.apply(new webpack.ProgressPlugin());

  // Step 2: Attach the dev middleware to the compiler & the server
  // Config options:
  //   see: https://github.com/webpack/webpack-dev-middleware
  //   see: https://webpack.js.org/configuration/dev-server/
  //   see: https://webpack.js.org/configuration/stats/
  //   see: https://webpack.github.io/docs/webpack-dev-server.html
  //   see: https://github.com/chimurai/http-proxy-middleware
  //   see: https://github.com/bripkens/connect-history-api-fallback
  //   NOTE: Only use options compatible with webpack-dev-middleware
  const webpackDevMiddleware = require('webpack-dev-middleware'); // eslint-disable-line global-require

  devMiddleware = webpackDevMiddleware(webpackCompiler, {
    publicPath: config.server.publicPath,
    stats: 'errors-only',
    /*
    stats: {
      errors: true,
      colors: true,
    },
    */
  });
  app.use(devMiddleware);

  // Step 3: Attach the hot middleware to the compiler & the server
  // Config options:
  //   See: https://github.com/glenjamin/webpack-hot-middleware
  if (config.isHot) {
    app.use(require('webpack-hot-middleware')(webpackCompiler));

    /*
    const webpackHotMiddleware = require('webpack-hot-middleware'); // eslint-disable-line global-require
    const hotMiddleware = webpackHotMiddleware(webpackCompiler, {
      path: '/__webpack_hmr'
      // You can use full urls, like:
      // path: `http://${host}:${port}${publicPath}/__webpack_hmr`
      // Remember to update webpack-hot-middleware in ../webpack-config.babel
    });
    app.use(hotMiddleware);
    */
  }

  // Add public path after step 3
  app.use(config.server.publicPath, express.static(config.server.contentBase));

  // Since webpackDevMiddleware uses memory-fs internally to store build
  // artifacts, we use it instead
  const memoryFs = devMiddleware.fileSystem;

  app.get('*', (req, res, next) => {

    const reqPath = req.path.startsWith(config.server.publicPath)
      ? req.path.replace(config.server.publicPath, '')
      : req.path;

    const target = reqPath.indexOf('.') > -1
      ? path.join(webpackCompiler.outputPath, reqPath)
      : path.join(webpackCompiler.outputPath, 'index.html');

    if (target.endsWith('.html')) {
      // 1: Read from memory fs
      logger.info('1 app.get * from:', req.path, 'to:', target);
      memoryFs.readFile(target, (err, file) => {
        if (err) {
          next(NotFoundException(req.path));
        } else {
          res.send(file.toString());
        }
      });
    }
    else {
      // 2: Try reading from outputPath, i.e. "dist"
      logger.info('2 app.get * from:', req.path, 'to:', target);
      res.sendFile(target, err => {
        if (err) {
          // 3: Try reading from src
          const src = path.join(config.server.contentBase, reqPath);
          logger.info('3 app.get * from:', req.path, 'to:', src);

          res.sendFile(src, err => {
            if (err) {
              next(NotFoundException(req.path));
            }
          });
        }
      });
    }
  });
}

// Catch 404 and forward to error handler
app.use(notFound);

// Error handlers
app.use(logErrors);          // Log errors
app.use(clientErrorHandler); // Client error handler
app.use(errorHandler);       // Catch all error handler

// See: https://nodejs.org/api/process.html#process_event_unhandledrejection
process.on('unhandledRejection', (reason, p) => {
  logger.error('Unhandled Rejection at:', p, 'reason:', reason);
});

// See: https://nodejs.org/api/process.html#process_event_uncaughtexception
process.on('uncaughtException', err => {
  logger.error('Server Uncaught Exception ', err);
  process.exit(1);
});

export default app;
export { devMiddleware };
<|endoftext|>


<commit_before>/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Startup
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

var app = require('http').createServer(function (request, response) { if (url.parse(request.url).pathname.indexOf("socket.io") <= 0)  { response.writeHead(301, { 'Location': 'http://langenium.com/play' }); } response.end(); })
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , url = require('url')
  , db = require("./db.js")
  , events = require("./events.js")
  , THREE = require('three');

app.listen(80);

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Socket event handlers
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
io.set('log level', 2);

var 	worldMap = [],
		bots = [];

buildWorldMap();
function buildWorldMap(){
	var map_builder = db.getDummyMap();
	map_builder.forEach(function(sceneObj, index){
		var 	type = sceneObj.type,
				object = db.getObject(type),
				scale = sceneObj.scale || object.scale,
				urlPrefix = "http://langenium.com/play/",
				loader =  new THREE.JSONLoader(),
				url = object.url;

		loader.load(urlPrefix + url, function(geometry, materials){
			var objMesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial( materials ) );
			objMesh.geometry.computeBoundingBox();

			objMesh.scale = new THREE.Vector3(scale,scale,scale);
			objMesh.position.x = sceneObj.position.x,
			objMesh.position.y = sceneObj.position.y,
			objMesh.position.z = sceneObj.position.z,
			objMesh.matrixAutoUpdate = true;
			objMesh.updateMatrix();
			objMesh.updateMatrixWorld();
			worldMap.push(objMesh);
		});
	});

	var bot_builder = db.getDummyEnemies();
	bot_builder.forEach(function(obj, index){
		var 	type = obj.type,
				object = db.getObject(type),
				scale = obj.scale || object.scale,
				urlPrefix = "http://langenium.com/play/",
				loader =  new THREE.JSONLoader(),
				url = object.url;

		loader.load(urlPrefix + url, function(geometry, materials){
			var objMesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial( materials ) );
			objMesh.geometry.computeBoundingBox();

			objMesh.scale = new THREE.Vector3(scale,scale,scale);
			objMesh.position.x = obj.position.x,
			objMesh.position.y = obj.position.y,
			objMesh.position.z = obj.position.z,
			objMesh.matrixAutoUpdate = true;
			objMesh.updateMatrix();
			objMesh.updateMatrixWorld();
			objMesh.username = obj.id;
			bots.push(objMesh);
		});
	});
}

io.sockets.on('connection', function (socket) {
	var time = new Date();
	function updateWorld() {
		var 	newTime = new Date(),
				delta = newTime = time;

		var velocityChange = 5;
		bots.forEach(function(bot, index){
			var 	newX = 0,
					newY = 0,
					newZ = 0,
					newRY = 0;

			newX = velocityChange * Math.sin(bot.rotation.y);
			newZ = velocityChange * Math.cos(bot.rotation.y);
			newY = Math.cos(delta/1000)/(1000*Math.random() );
			newRY =  Math.cos(delta/1000)/(1000*Math.random() );

			bots[index].position.x += newX;
			bots[index].position.y += newY;
			bots[index].position.z += newZ;
			bots[index].rotation.y += newRY;

			var data = { pX: newX, pY: newY, pZ: newZ, rY: newRY, username: bot.username };
			//console.log(data);
			socket.emit('update', { instruction: { name: "move", type: "bot", details: data } });
		});
		time = newTime;
	}
	var tick = setInterval(updateWorld, 1000 / 60);

	socket.emit("ping", { time: new Date().getTime(), latency: 0});
	socket.on("pong", function(data){
		var time = new Date().getTime();
		var latency = time - data.time;
		socket.emit("ping", { time: new Date().getTime(), latency: latency});
	});

	socket.on("login", function(data){
		var player = loginPlayer(socket.id, data.username);
		if (player.username.length > 0) {
			socket.emit('load', { instructions: initializeClient(player) });

			var ship = cloneObject(player);
			ship.type = {ship: "ship"}

			socket.broadcast.emit('load', { instructions: [ {name: "load", username: ship.username, type: ship.type, url: ship.url, position: ship.position, scale: ship.position.scale, rotationY: ship.position.rotationY} ] });
		}
		else {
			console.log("Login failure");
		}
	});
	socket.on("disconnect" , function ()  {
		players_online.forEach(function(player, index){
			if (player.sessionId == socket.id) {
				socket.broadcast.emit('playerDisconnected', { username: player.username }); // change to sessionID later
				players_online.splice(index, 1);
			}
		});
		delete socket;
	});

	socket.on('move', function(data){
		players_online.forEach(function(player, index){
			if (player.sessionId == socket.id) {

				var playerMovement = events.movePlayer(players_online[index].position.rotationY, data);

				var moveVector = new THREE.Vector3(playerMovement.instruction.details.pX, playerMovement.instruction.details.pY, playerMovement.instruction.details.pZ);

				var playerObj = db.getObject({ship: 'mercenary'});
				var playerMesh = new THREE.Vector3(players_online[index].position.x, players_online[index].position.y, players_online[index].position.z);

				var raycaster = new THREE.Raycaster(playerMesh, moveVector.normalize());
				var intersects = raycaster.intersectObjects(worldMap);

				var util = require('util');
				if (intersects.length > 0) {
					intersects.forEach(function(obj, index){
						if (obj.distance < 100) {
							if (players_online[index].position.rotationY > 0)
								{ playerMovement.instruction.details.rY += obj.distance / 10000; }
							else
								{ playerMovement.instruction.details.rY -= obj.distance / 10000; }

							if (playerMovement.instruction.details.pX != 0) {
								playerMovement.instruction.details.pX *= -.1;
							}
							if (playerMovement.instruction.details.pY != 0) {
								playerMovement.instruction.details.pY *= -.1;
							}
							if (playerMovement.instruction.details.pZ != 0) {
								playerMovement.instruction.details.pZ *= -.1;
							}
						}
					});
				}
				players_online[index].position.y += playerMovement.instruction.details.pY;
				players_online[index].position.x += playerMovement.instruction.details.pX;
				players_online[index].position.z += playerMovement.instruction.details.pZ;
				playerMovement.instruction.details.username = socket.id;
				players_online[index].position.rotationY +=  playerMovement.instruction.details.rY;
				socket.emit('update', playerMovement);
				socket.broadcast.emit('update', playerMovement);
			}
		});
	});
});

// ENGINE VARIABLES
var players_online = [];
var players = [
		{ username: "Mercenary", id: "1", type: { ship: "player" }, url: "assets/mercenary.js", position: { x: -8122, y: 3656, z: -1740 , scale: 10, rotationY: 0 }},
		//{ username: "Pirate", uid: "2", type: "player", url: "assets/pirate.js", position: { x: -1000, y: 3000, z: 5500 , scale: 10, rotationY: 0 }}
		{ username: "Pirate", id: "2", type: { ship: "player" }, url: "assets/pirate.js", position: { x: 0, y: 0, z: 0 , scale: 10, rotationY: 0 }}
	];

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Client Events
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
function loginPlayer(sessionId, username) {
	var retval;
	players.forEach(function(player){
		if (player.username == username) {
			var online_player = cloneObject(player);
			online_player.username = sessionId;
			online_player.sessionId = sessionId;
			players_online.push(online_player);
			players_online[players_online.length-1].sessionId = sessionId;
			retval = online_player;
		}
	});
	return retval;
}

function initializeClient(activePlayer) {
	var initial_instructions = [];

	db.getLoadInstructions("map").forEach(function(instruction){ instruction.name = "load"; initial_instructions.push(instruction);});
	db.getLoadInstructions("ships").forEach(function(instruction){ instruction.name = "load"; initial_instructions.push(instruction);});

	//getLoadInstructions("ships").forEach(function(instruction){initial_instructions.push(instruction);});

	players_online.forEach(function(player, index){
		if (player.username != activePlayer.username) {
			// had to do this to de-reference player so that changing .type didn't override
			var ship = cloneObject(player);
			ship.type = { ship: "ship" };
			initial_instructions.push({name: "load", username: ship.username, type: ship.type, url: ship.url, position: ship.position, scale: ship.position.scale, rotationY: ship.position.rotationY});
		}
		else {
			initial_instructions.push({name: "load", username: player.username, type: player.type, url: player.url, position: player.position, scale: player.position.scale, rotationY: player.position.rotationY});
		}
	});
	return initial_instructions;
}

function cloneObject(obj) {
        var clone = {};
        for(var i in obj) {
            if(typeof(obj[i])=="object")
                clone[i] = cloneObject(obj[i]);
            else
                clone[i] = obj[i];
        }
        return clone;
}

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Utility functions
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

function spawn(uid, position) {
	position.scale = 10;
	return { name: "load", details: { uid: uid, type: "monster", url: "assets/pirate.js", position: position}};
}

<commit_msg>Cleaned up a little<commit_after>/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Startup
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

var app = require('http').createServer(function (request, response) { if (url.parse(request.url).pathname.indexOf("socket.io") <= 0)  { response.writeHead(301, { 'Location': 'http://langenium.com/play' }); } response.end(); })
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , url = require('url')
  , db = require("./db.js")
  , events = require("./events.js")
  , THREE = require('three');

app.listen(80);

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Socket event handlers
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
io.set('log level', 2);

var 	worldMap = [],
		bots = [];

buildWorldMap();
function buildWorldMap(){
	var map_builder = db.getDummyMap();
	map_builder.forEach(function(sceneObj, index){
		var 	type = sceneObj.type,
				object = db.getObject(type),
				scale = sceneObj.scale || object.scale,
				urlPrefix = "http://langenium.com/play/",
				loader =  new THREE.JSONLoader(),
				url = object.url;

		loader.load(urlPrefix + url, function(geometry, materials){
			var objMesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial( materials ) );
			objMesh.geometry.computeBoundingBox();

			objMesh.scale = new THREE.Vector3(scale,scale,scale);
			objMesh.position.x = sceneObj.position.x,
			objMesh.position.y = sceneObj.position.y,
			objMesh.position.z = sceneObj.position.z,
			objMesh.matrixAutoUpdate = true;
			objMesh.updateMatrix();
			objMesh.updateMatrixWorld();
			worldMap.push(objMesh);
		});
	});

	var bot_builder = db.getDummyEnemies();
	bot_builder.forEach(function(obj, index){
		var 	type = obj.type,
				object = db.getObject(type),
				scale = obj.scale || object.scale,
				urlPrefix = "http://langenium.com/play/",
				loader =  new THREE.JSONLoader(),
				url = object.url;

		loader.load(urlPrefix + url, function(geometry, materials){
			var objMesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial( materials ) );
			objMesh.geometry.computeBoundingBox();

			objMesh.scale = new THREE.Vector3(scale,scale,scale);
			objMesh.position.x = obj.position.x,
			objMesh.position.y = obj.position.y,
			objMesh.position.z = obj.position.z,
			objMesh.matrixAutoUpdate = true;
			objMesh.updateMatrix();
			objMesh.updateMatrixWorld();
			objMesh.username = obj.id;
			bots.push(objMesh);
		});
	});
}

var time = new Date();
function updateWorld() {
	var 	newTime = new Date(),
			delta = newTime = time;

	var velocityChange = -5;
	bots.forEach(function(bot, index){
		var 	newX = 0,
				newY = 0,
				newZ = 0,
				newRY = 0;

		newRY = Math.cos(delta/1000)/(Math.random() * 100 - 200);

		newX = velocityChange * Math.sin(bot.rotation.y + newRY);
		newZ = velocityChange * Math.cos(bot.rotation.y + newRY);
		newY = Math.cos(delta/1000)/(1000*Math.random() );

		bots[index].position.x += newX;
		bots[index].position.y += newY;
		bots[index].position.z += newZ;
		bots[index].rotation.y += newRY;

		var data = { pX: newX, pY: newY, pZ: newZ, rY: newRY, username: bot.username };
		//console.log(data);
		io.sockets.emit('update', { instruction: { name: "move", type: "bot", details: data } });
	});
	time = newTime;
}
var tick = setInterval(updateWorld, 1000 / 33);

io.sockets.on('connection', function (socket) {
	socket.emit("ping", { time: new Date().getTime(), latency: 0});
	socket.on("pong", function(data){
		var time = new Date().getTime();
		var latency = time - data.time;
		socket.emit("ping", { time: new Date().getTime(), latency: latency});
	});

	socket.on("login", function(data){
		var player = loginPlayer(socket.id, data.username);
		if (player.username.length > 0) {
			socket.emit('load', { instructions: initializeClient(player) });

			var ship = cloneObject(player);
			ship.type = {ship: "ship"}

			socket.broadcast.emit('load', { instructions: [ {name: "load", username: ship.username, type: ship.type, url: ship.url, position: ship.position, scale: ship.position.scale, rotationY: ship.position.rotationY} ] });
		}
		else {
			console.log("Login failure");
		}
	});
	socket.on("disconnect" , function ()  {
		players_online.forEach(function(player, index){
			if (player.sessionId == socket.id) {
				socket.broadcast.emit('playerDisconnected', { username: player.username }); // change to sessionID later
				players_online.splice(index, 1);
			}
		});
		delete socket;
	});

	socket.on('move', function(data){
		players_online.forEach(function(player, index){
			if (player.sessionId == socket.id) {

				var playerMovement = events.movePlayer(players_online[index].position.rotationY, data);

				var moveVector = new THREE.Vector3(playerMovement.instruction.details.pX, playerMovement.instruction.details.pY, playerMovement.instruction.details.pZ);

				var playerObj = db.getObject({ship: 'mercenary'});
				var playerMesh = new THREE.Vector3(players_online[index].position.x, players_online[index].position.y, players_online[index].position.z);

				var raycaster = new THREE.Raycaster(playerMesh, moveVector.normalize());
				var intersects = raycaster.intersectObjects(worldMap);

				var util = require('util');
				if (intersects.length > 0) {
					intersects.forEach(function(obj, index){
						if (obj.distance < 100) {
							if (players_online[index].position.rotationY > 0)
								{ playerMovement.instruction.details.rY += obj.distance / 10000; }
							else
								{ playerMovement.instruction.details.rY -= obj.distance / 10000; }

							if (playerMovement.instruction.details.pX != 0) {
								playerMovement.instruction.details.pX *= -.1;
							}
							if (playerMovement.instruction.details.pY != 0) {
								playerMovement.instruction.details.pY *= -.1;
							}
							if (playerMovement.instruction.details.pZ != 0) {
								playerMovement.instruction.details.pZ *= -.1;
							}
						}
					});
				}
				players_online[index].position.y += playerMovement.instruction.details.pY;
				players_online[index].position.x += playerMovement.instruction.details.pX;
				players_online[index].position.z += playerMovement.instruction.details.pZ;
				playerMovement.instruction.details.username = socket.id;
				players_online[index].position.rotationY +=  playerMovement.instruction.details.rY;
				socket.emit('update', playerMovement);
				socket.broadcast.emit('update', playerMovement);
			}
		});
	});
});

// ENGINE VARIABLES
var players_online = [];
var players = [
		{ username: "Mercenary", id: "1", type: { ship: "player" }, url: "assets/mercenary.js", position: { x: -8500, y: 3900, z: -1740 , scale: 10, rotationY: 3.14 }},
		//{ username: "Pirate", uid: "2", type: "player", url: "assets/pirate.js", position: { x: -1000, y: 3000, z: 5500 , scale: 10, rotationY: 0 }}
		{ username: "Pirate", id: "2", type: { ship: "player" }, url: "assets/pirate.js", position: { x: 0, y: 0, z: 0 , scale: 10, rotationY: 0 }}
	];

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// w//////////////////////
	Client Events
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
function loginPlayer(sessionId, username) {
	var retval;
	players.forEach(function(player){
		if (player.username == username) {
			var online_player = cloneObject(player);
			online_player.username = sessionId;
			online_player.sessionId = sessionId;
			players_online.push(online_player);
			players_online[players_online.length-1].sessionId = sessionId;
			retval = online_player;
		}
	});
	return retval;
}

function initializeClient(activePlayer) {
	var initial_instructions = [];

	db.getLoadInstructions("map").forEach(function(instruction){ instruction.name = "load"; initial_instructions.push(instruction);});
	db.getLoadInstructions("ships").forEach(function(instruction){ instruction.name = "load"; initial_instructions.push(instruction);});

	//getLoadInstructions("ships").forEach(function(instruction){initial_instructions.push(instruction);});

	players_online.forEach(function(player, index){
		if (player.username != activePlayer.username) {
			// had to do this to de-reference player so that changing .type didn't override
			var ship = cloneObject(player);
			ship.type = { ship: "ship" };
			initial_instructions.push({name: "load", username: ship.username, type: ship.type, url: ship.url, position: ship.position, scale: ship.position.scale, rotationY: ship.position.rotationY});
		}
		else {
			initial_instructions.push({name: "load", username: player.username, type: player.type, url: player.url, position: player.position, scale: player.position.scale, rotationY: player.position.rotationY});
		}
	});
	return initial_instructions;
}

function cloneObject(obj) {
        var clone = {};
        for(var i in obj) {
            if(typeof(obj[i])=="object")
                clone[i] = cloneObject(obj[i]);
            else
                clone[i] = obj[i];
        }
        return clone;
}

/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Utility functions
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

function spawn(uid, position) {
	position.scale = 10;
	return { name: "load", details: { uid: uid, type: "monster", url: "assets/pirate.js", position: position}};
}

<|endoftext|>


<commit_before>"use strict";

var F_FECHA_HORA='DD/MM hh:mm:ss';

var guardar={};
var planillas=[];
var planillas_orden=[];
var planillas_momento=[];
traerDeLS();

function indexarPlanilla(planilla){
    planillas_orden[planilla.orden]=planilla;
    var idxMomento=planilla.momento+' i '+planilla.orden;
    planillas_momento[idxMomento]=planilla;
};

function traerDeLS(){
    guardar=localStorage['ch.guardar'];
    guardar=guardar?JSON.parse(guardar):{planillas:[]};
    planillas=guardar.planillas;
    for(var i=0; i<planillas.length; i++){
        var planilla=planillas[i];
        indexarPlanilla(planilla);
    }
}

if(typeof moment == "undefined"){
    window.moment={format:function(){ return "moment no instalado";}};
}

function refrescarPlanillas(){
    planillas_div.innerHTML='';
    var div=document.createElement('div');
    var button=document.createElement('button');
    button.textContent='nuevo';
    button.id='nuevo';
    button.onclick=function(){
        mostrarPantallaIngreso(null,true);
    }
    div.appendChild(button);
    planillas_div.appendChild(div);
    var div=document.createElement('div');
    var button=document.createElement('button');
    button.textContent='dump';
    button.id='dump';
    button.onclick=function(){
        contenido.innerHTML='';
        contenido.textContent=JSON.stringify(planillas);
    }
    div.appendChild(button);
    planillas_div.appendChild(div);
    var div=document.createElement('div');
    var button=document.createElement('button');
    if(!"con boton demo"){
        button.textContent='DEMO';
        button.id='demo';
        button.onclick=function(){
            for(var i=5000; i<9999; i++){
                if(!(i in planillas)){
                    var planilla={orden:i, momento:moment().subtract(i,'seconds')};
                    for(var nombre in estructura.variables){
                        var def=estructura.variables[nombre];
                        planilla[nombre]=nombre=='orden'?i:Math.floor(Math.random()*(Math.pow(10,def.ancho)));
                    }
                    planillas.push(planilla);
                    indexarPlanilla(planilla);
                }
            }
            refrescarPlanillas();
        }
        div.appendChild(button);
        planillas_div.appendChild(div);
    }
    item_cantidad.textContent=planillas.length+' planillas';
    var momentos_planilla=Object.keys(planillas_momento);
    momentos_planilla.sort();
    momentos_planilla.reverse();
    for(var i=0; i<momentos_planilla.length; i++){
        var planilla=planillas_momento[momentos_planilla[i]];
        if(i<estructura.maxPlanillasLateral){
            var div=document.createElement('div');
            var button=document.createElement('button');
            button.textContent=planilla.orden+' '+moment(planilla.momento).format(F_FECHA_HORA);
            button.dataset.sucia = !!planilla.sucia;
            button.onclick=(function(orden){
                return function(){
                    mostrarPantallaIngreso(orden,false);
                };
            })(planilla.orden);
            div.appendChild(button);
            planillas_div.appendChild(div);
        }
    }
}

function ajaxSimple(params){
    var ajax = new XMLHttpRequest();
    params.onerror=params.onerror||function(err){ alert(err); };
    ajax.open(params.method||'get',params.url);
    ajax.onload=function(e){
        if(ajax.status!=200){
            params.onerror(new Error(ajax.status+' '+ajax.responseText));
        }else{
            try{
                params.onload.call(null,ajax.responseText);
            }catch(err){
                params.onerror(err);
            }
        }
    }
    ajax.onerror=params.onerror;
    ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    var enviar=Object.keys(params.data).map(function(key){
        return key+'='+encodeURIComponent(params.data[key]);
    }).join('&');
    ajax.send(enviar);
}

function sincronizarConElServidor(){
    item_status.textContent='sincronizando...';
    setTimeout(function(){
        var planillasAEnviar=planillas.filter(function(planilla){
            return planilla.sucia;
        });
        ajaxSimple({
            method:'POST',
            url:'/syncro/put',
            data:{planillas:JSON.stringify(planillasAEnviar)},
            onload:function(data){
                item_status.textContent='actualizado '+data;
                planillasAEnviar.forEach(function(planilla){
                    planilla.sucia=false;
                });
                refrescarPlanillas();
            },
            onerror:function(err){
                item_status.textContent='error';
                item_status.title=err+'';
            },
        });
    },0);
}

function mostrarPantallaIngreso(numeroOrden,doFocus){
    var nuevo=true;
    var vacio=true;
    var planilla={};
    var primerEditable=null;
    if(numeroOrden && !isNaN(numeroOrden)){
        vacio=false;
        var planilla=planillas_orden[numeroOrden];
        if(planilla){
            nuevo=false;
        }else{
            planilla={momento:moment(), orden:Number(numeroOrden)};
            planillas.push(planilla);
            indexarPlanilla(planilla);
        }
        var buttonSave=document.createElement('button');
        buttonSave.dataset.saved=true;
        buttonSave.textContent='grabar';
        buttonSave.id='grabar';
        buttonSave.onclick=function(){
            planilla.sucia=true;
            item_status.textContent='saving';
            buttonSave.disabled=true;
            setTimeout(function(){
                for(var nombre in estructura.variables){
                    planilla[nombre]=referencias[nombre].textContent;
                }
                localStorage['ch.guardar']=JSON.stringify(guardar);
                buttonSave.dataset.saved=true;
                item_status.textContent='ok';
                buttonSave.enabled=true;
                refrescarPlanillas();
                item_status.textContent='sincronizando';
                setTimeout(function(){
                    sincronizarConElServidor();
                },0);
            },0);
        }
    }
    contenido.innerHTML='';
    var table=document.createElement('table');
    var referencias={};
    for(var nombre in estructura.variables){
        var def=estructura.variables[nombre];
        var fila=table.insertRow(-1);
        var cell=fila.insertCell(-1);
        cell.textContent=def.leyenda||nombre;
        if(!(nombre in planilla)){
            planilla[nombre]=null;
        }
        cell=fila.insertCell(-1);
        var editable=!!def.esId===vacio
        cell.contentEditable=editable;
        if(editable && !primerEditable){
            primerEditable=cell;
        }
        cell.dataset.varname=nombre;
        cell.textContent=planilla[nombre];
        cell.id='nueva_'+nombre;
        referencias[nombre]=cell;
        cell.onblur=function(){
            buttonSave.dataset.saved=false;
        }
        cell.onkeydown=enter2tab;
        cell.className='campo';
        if(def.ancho>6){
            cell.colSpan=2;
        }
        if(def.esId && vacio){
            cell=fila.insertCell(-1);
            var button=document.createElement('button');
            button.textContent='ingresar';
            button.onclick=function(){
                mostrarPantallaIngreso(Number(referencias.orden.textContent),true);
            }
            cell.appendChild(button);
        }
    }
    if(!vacio){
        var row=table.insertRow(-1);
        var cell=row.insertCell(-1);
        cell.colSpan=2;
        var cell=row.insertCell(-1);
        cell.appendChild(buttonSave);
    }
    contenido.appendChild(table);
    if(primerEditable && doFocus){
        primerEditable.focus();
    }
}

window.addEventListener('load',function(){
    refrescarPlanillas();
    var button=document.createElement('button');
    button.id='sincronizar';
    button.textContent='sincronizar';
    button.onclick=sincronizarConElServidor;
    item_sincronizar.appendChild(button);
});

function enter2tab(e) {
    if (e.which == 13) {
        var row=e.target.parentElement;
        row.parentElement.rows[row.rowIndex+1].cells[e.target.cellIndex].focus();
        e.preventDefault();
    }
}
<commit_msg>paths<commit_after>"use strict";

var F_FECHA_HORA='DD/MM hh:mm:ss';

var guardar={};
var planillas=[];
var planillas_orden=[];
var planillas_momento=[];
traerDeLS();

function indexarPlanilla(planilla){
    planillas_orden[planilla.orden]=planilla;
    var idxMomento=planilla.momento+' i '+planilla.orden;
    planillas_momento[idxMomento]=planilla;
};

function traerDeLS(){
    guardar=localStorage['ch.guardar'];
    guardar=guardar?JSON.parse(guardar):{planillas:[]};
    planillas=guardar.planillas;
    for(var i=0; i<planillas.length; i++){
        var planilla=planillas[i];
        indexarPlanilla(planilla);
    }
}

if(typeof moment == "undefined"){
    window.moment={format:function(){ return "moment no instalado";}};
}

function refrescarPlanillas(){
    planillas_div.innerHTML='';
    var div=document.createElement('div');
    var button=document.createElement('button');
    button.textContent='nuevo';
    button.id='nuevo';
    button.onclick=function(){
        mostrarPantallaIngreso(null,true);
    }
    div.appendChild(button);
    planillas_div.appendChild(div);
    var div=document.createElement('div');
    var button=document.createElement('button');
    button.textContent='dump';
    button.id='dump';
    button.onclick=function(){
        contenido.innerHTML='';
        contenido.textContent=JSON.stringify(planillas);
    }
    div.appendChild(button);
    planillas_div.appendChild(div);
    var div=document.createElement('div');
    var button=document.createElement('button');
    if(!"con boton demo"){
        button.textContent='DEMO';
        button.id='demo';
        button.onclick=function(){
            for(var i=5000; i<9999; i++){
                if(!(i in planillas)){
                    var planilla={orden:i, momento:moment().subtract(i,'seconds')};
                    for(var nombre in estructura.variables){
                        var def=estructura.variables[nombre];
                        planilla[nombre]=nombre=='orden'?i:Math.floor(Math.random()*(Math.pow(10,def.ancho)));
                    }
                    planillas.push(planilla);
                    indexarPlanilla(planilla);
                }
            }
            refrescarPlanillas();
        }
        div.appendChild(button);
        planillas_div.appendChild(div);
    }
    item_cantidad.textContent=planillas.length+' planillas';
    var momentos_planilla=Object.keys(planillas_momento);
    momentos_planilla.sort();
    momentos_planilla.reverse();
    for(var i=0; i<momentos_planilla.length; i++){
        var planilla=planillas_momento[momentos_planilla[i]];
        if(i<estructura.maxPlanillasLateral){
            var div=document.createElement('div');
            var button=document.createElement('button');
            button.textContent=planilla.orden+' '+moment(planilla.momento).format(F_FECHA_HORA);
            button.dataset.sucia = !!planilla.sucia;
            button.onclick=(function(orden){
                return function(){
                    mostrarPantallaIngreso(orden,false);
                };
            })(planilla.orden);
            div.appendChild(button);
            planillas_div.appendChild(div);
        }
    }
}

function ajaxSimple(params){
    var ajax = new XMLHttpRequest();
    params.onerror=params.onerror||function(err){ alert(err); };
    ajax.open(params.method||'get',params.url);
    ajax.onload=function(e){
        if(ajax.status!=200){
            params.onerror(new Error(ajax.status+' '+ajax.responseText));
        }else{
            try{
                params.onload.call(null,ajax.responseText);
            }catch(err){
                params.onerror(err);
            }
        }
    }
    ajax.onerror=params.onerror;
    ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    var enviar=Object.keys(params.data).map(function(key){
        return key+'='+encodeURIComponent(params.data[key]);
    }).join('&');
    ajax.send(enviar);
}

function sincronizarConElServidor(){
    item_status.textContent='sincronizando...';
    setTimeout(function(){
        var planillasAEnviar=planillas.filter(function(planilla){
            return planilla.sucia;
        });
        ajaxSimple({
            method:'POST',
            url:'./syncro/put',
            data:{planillas:JSON.stringify(planillasAEnviar)},
            onload:function(data){
                item_status.textContent='actualizado '+data;
                planillasAEnviar.forEach(function(planilla){
                    planilla.sucia=false;
                });
                refrescarPlanillas();
            },
            onerror:function(err){
                item_status.textContent='error';
                item_status.title=err+'';
            },
        });
    },0);
}

function mostrarPantallaIngreso(numeroOrden,doFocus){
    var nuevo=true;
    var vacio=true;
    var planilla={};
    var primerEditable=null;
    if(numeroOrden && !isNaN(numeroOrden)){
        vacio=false;
        var planilla=planillas_orden[numeroOrden];
        if(planilla){
            nuevo=false;
        }else{
            planilla={momento:moment(), orden:Number(numeroOrden)};
            planillas.push(planilla);
            indexarPlanilla(planilla);
        }
        var buttonSave=document.createElement('button');
        buttonSave.dataset.saved=true;
        buttonSave.textContent='grabar';
        buttonSave.id='grabar';
        buttonSave.onclick=function(){
            planilla.sucia=true;
            item_status.textContent='saving';
            buttonSave.disabled=true;
            setTimeout(function(){
                for(var nombre in estructura.variables){
                    planilla[nombre]=referencias[nombre].textContent;
                }
                localStorage['ch.guardar']=JSON.stringify(guardar);
                buttonSave.dataset.saved=true;
                item_status.textContent='ok';
                buttonSave.enabled=true;
                refrescarPlanillas();
                item_status.textContent='sincronizando';
                setTimeout(function(){
                    sincronizarConElServidor();
                },0);
            },0);
        }
    }
    contenido.innerHTML='';
    var table=document.createElement('table');
    var referencias={};
    for(var nombre in estructura.variables){
        var def=estructura.variables[nombre];
        var fila=table.insertRow(-1);
        var cell=fila.insertCell(-1);
        cell.textContent=def.leyenda||nombre;
        if(!(nombre in planilla)){
            planilla[nombre]=null;
        }
        cell=fila.insertCell(-1);
        var editable=!!def.esId===vacio
        cell.contentEditable=editable;
        if(editable && !primerEditable){
            primerEditable=cell;
        }
        cell.dataset.varname=nombre;
        cell.textContent=planilla[nombre];
        cell.id='nueva_'+nombre;
        referencias[nombre]=cell;
        cell.onblur=function(){
            buttonSave.dataset.saved=false;
        }
        cell.onkeydown=enter2tab;
        cell.className='campo';
        if(def.ancho>6){
            cell.colSpan=2;
        }
        if(def.esId && vacio){
            cell=fila.insertCell(-1);
            var button=document.createElement('button');
            button.textContent='ingresar';
            button.onclick=function(){
                mostrarPantallaIngreso(Number(referencias.orden.textContent),true);
            }
            cell.appendChild(button);
        }
    }
    if(!vacio){
        var row=table.insertRow(-1);
        var cell=row.insertCell(-1);
        cell.colSpan=2;
        var cell=row.insertCell(-1);
        cell.appendChild(buttonSave);
    }
    contenido.appendChild(table);
    if(primerEditable && doFocus){
        primerEditable.focus();
    }
}

window.addEventListener('load',function(){
    refrescarPlanillas();
    var button=document.createElement('button');
    button.id='sincronizar';
    button.textContent='sincronizar';
    button.onclick=sincronizarConElServidor;
    item_sincronizar.appendChild(button);
});

function enter2tab(e) {
    if (e.which == 13) {
        var row=e.target.parentElement;
        row.parentElement.rows[row.rowIndex+1].cells[e.target.cellIndex].focus();
        e.preventDefault();
    }
}
<|endoftext|>