rewrite: merge in some more litenull stuff & delete the superfluous files
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"directory": "app/bower_components"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
HabitRPG Rewrite
|
||||
===============
|
||||
|
||||
HabitRPG Rewrite under development. Built using Angular.
|
||||
|
||||
**Note: This branch is under development, and these instructions may fall out of date. They were accurate as of August 5, 2013.** Should you encounter this, join #habitrpg on IRC (Freenode) and talk to litenull.
|
||||
|
||||
The general steps are:
|
||||
|
||||
1. Set up and run the [server](https://github.com/lefnire/habitrpg/wiki/Running-Locally-%28Server%29)
|
||||
1. Clone the repo
|
||||
1. Install all dependencies
|
||||
1. Run the client
|
||||
|
||||
Or, expressed in commands on the command line:
|
||||
|
||||
1. `git clone --branch angular_rewrite git://github.com/lefnire/habitrpg habitrpg-angular`
|
||||
1. `npm install`
|
||||
1. `bower install` (if you don't have `bower`, do `npm install -g bower` — might need `sudo`)
|
||||
1. `node server.js`
|
||||
|
||||
To access the site, open http://localhost:3003 in your browser.
|
||||
@@ -1,132 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en" ng-app="habitrpg" ng-controller="RootCtrl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||
<title>HabitRPG</title>
|
||||
<link href='//fonts.googleapis.com/css?family=Lato:300,300italic' rel='stylesheet' type='text/css'>
|
||||
<style>
|
||||
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body ng-cloak>
|
||||
|
||||
<div ng-controller="WrapperCtrl">
|
||||
<div id="undefined-sticky-wrapper" class="sticky-wrapper">
|
||||
<div class="header-wrap">
|
||||
<div class="user-menu">
|
||||
<ul class="nav site-nav">
|
||||
<li class="flyout">
|
||||
<h1 class="task-action-btn tile solid user-reporter">
|
||||
<div ng-show="user.auth.local.username">{{user.auth.local.username}}</div>
|
||||
</h1>
|
||||
|
||||
<ul class="flyout-content nav stacked">
|
||||
<li>
|
||||
<a class="task-action-btn tile solid" ng-click="showMenu()">Options</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="task-action-btn tile solid" href="" ng-click="logout()">Logout</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-controller="CharacterCtrl">
|
||||
<header class="site-header" role="banner">
|
||||
<div class="herobox-wrap main-herobox" ng-click="showMenu()">
|
||||
|
||||
<figure class="herobox"
|
||||
data-name="{{user.auth.local.username}}"
|
||||
data-level="{{user.stats.lvl}}"
|
||||
data-checkuser="isUser"
|
||||
>
|
||||
<div class='character-sprites'>
|
||||
<span class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}'></span>
|
||||
<span class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}'></span>
|
||||
<span class="{{user.preferences.gender}}_armor_{{user.items.armor}}"></span>
|
||||
<span class="{{equipped(user, 'head')}}"></span>
|
||||
<span class="{{user.preferences.gender}}_head_0"></span>
|
||||
<span class='{{user.preferences.gender}}_shield_{{user.items.shield}}'></span>
|
||||
<span class='{{user.preferences.gender}}_weapon_{{user.items.weapon}}'></span>
|
||||
</div>
|
||||
</figure>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hero-stats">
|
||||
<div class="meter health" Title="Health">
|
||||
<div class="bar" style="width:{{hpPercent(user.stats.hp)}}%"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="meter experience" Title="Experience">
|
||||
<div class="bar" style="width:{{expPercent(user.stats.exp, user.stats.lvl)}}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
|
||||
<div ng-view></div>
|
||||
|
||||
<!-- Exclude these from the build process, minify borks angular dep-inj var names like $scope -->
|
||||
<!-- See http://docs.angularjs.org/guide/di "$injection Annotation" for when we're ready to deploy -->
|
||||
<script src="bower_components/angular/angular.js"></script>
|
||||
<script src="bower_components/angular-resource/angular-resource.js"></script>
|
||||
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
|
||||
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
|
||||
|
||||
|
||||
<!-- build:js scripts/scripts.js -->
|
||||
|
||||
<!-- Vendor -->
|
||||
<script src="bower_components/underscore/underscore-min.js"></script>
|
||||
<script src="bower_components/moment/moment.js"></script>
|
||||
<script src="scripts/vendor/cdv-plugin-fb-connect.js"></script>
|
||||
<script src="scripts/vendor/facebook-js-sdk.js"></script>
|
||||
<script src="bower_components/jquery/jquery.min.js"></script>
|
||||
<script src="scripts/vendor/jquery-ui-1.10.3.custom.js"></script>
|
||||
<!-- touch events (bower: hammerjs and monospaced/angular-hammer) -->
|
||||
<script src="bower_components/hammerjs/dist/hammer.min.js"></script>
|
||||
<script src="bower_components/hammerjs/dist/jquery.hammer.min.js"></script>
|
||||
<script src="bower_components/angular-hammer/angular-hammer.js"></script>
|
||||
|
||||
<!-- HabitRPG Shared -->
|
||||
<script src="bower_components/habitrpg-shared/browser/browser.debug.js"></script>
|
||||
<script src="scripts/vendor/jquery.transit.min.js"></script>
|
||||
|
||||
<!-- App -->
|
||||
<script src="scripts/app.js"></script>
|
||||
<script src="scripts/controllers/rootCtrl.js"></script>
|
||||
<script src="scripts/controllers/settingsCtrl.js"></script>
|
||||
<script src="scripts/filters/filters.js"></script>
|
||||
<script src="scripts/controllers/tasksCtrl.js"></script>
|
||||
<script src="scripts/controllers/taskDetailsCtrl.js"></script>
|
||||
<script src="scripts/directives/taskFocus.js"></script>
|
||||
<script src="scripts/directives/taskBlur.js"></script>
|
||||
<script src="scripts/controllers/navCtrl.js"></script>
|
||||
<script src="scripts/controllers/wrapperCtrl.js"></script>
|
||||
<script src="scripts/controllers/statsCtrl.js"></script>
|
||||
<script src="scripts/controllers/characterCtrl.js"></script>
|
||||
<script src="scripts/controllers/menuCtrl.js"></script>
|
||||
<script src="scripts/controllers/authCtrl.js"></script>
|
||||
<script src="scripts/services/userServices.js"></script>
|
||||
<script src="scripts/services/sharedServices.js"></script>
|
||||
<script src="scripts/services/authServices.js"></script>
|
||||
<script src="scripts/services/notificationServices.js"></script>
|
||||
<script src="scripts/controllers/notificationCtrl.js"></script>
|
||||
<script src="scripts/controllers/loginCtrl.js"></script>
|
||||
<script src="scripts/controllers/eventCtrl.js"></script>
|
||||
<script src="scripts/controllers/userAvatarCtrl.js"></script>
|
||||
<!-- endbuild -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,74 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The main HabitRPG app module.
|
||||
*
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
|
||||
var habitrpg = angular.module('habitrpg', ['userServices', 'sharedServices', 'authServices', 'notificationServices', 'hmTouchEvents'])
|
||||
.config(['$routeProvider', function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/home', {templateUrl: 'views/home.html'})
|
||||
.when('/login', {templateUrl: 'views/login.html'})
|
||||
.when('/settings', {templateUrl: 'views/settings.html'})
|
||||
.when('/profile', {templateUrl: 'views/profile.html'})
|
||||
.when('/options', {templateUrl: 'views/options.html'})
|
||||
.when('/:action', {templateUrl: 'views/list.html'})
|
||||
.when('/tasks/:taskId', {templateUrl: 'views/details.html'})
|
||||
.when('/todo/active', {templateUrl: 'views/list.html'})
|
||||
.when('/todo/completed', {templateUrl: 'views/list.html'})
|
||||
.otherwise({redirectTo: '/habit'});
|
||||
}])
|
||||
.config(['$compileProvider', function ($compileProvider) {
|
||||
$compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
|
||||
}]);
|
||||
|
||||
|
||||
// Touch directive, binding to touchstart as to not wait for 300ms
|
||||
|
||||
habitrpg.directive('gfTap', ["$location", "$parse", function ($location, $parse) {
|
||||
return function (scope, element, attrs) {
|
||||
var tapping = false;
|
||||
element.bind('touchstart', function () {
|
||||
tapping = true;
|
||||
});
|
||||
|
||||
element.bind('touchmove', function () {
|
||||
tapping = false
|
||||
});
|
||||
|
||||
element.bind('touchend', function (event) {
|
||||
if (tapping) {
|
||||
var fn = $parse(attrs['gfTap']);
|
||||
|
||||
if (attrs['href']) {
|
||||
var location = attrs['href'].replace('#', '/');
|
||||
$location.path(location);
|
||||
}
|
||||
|
||||
scope.$apply(function () {
|
||||
fn(scope, {$event: event})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
}]);
|
||||
|
||||
habitrpg.directive('sort', function (User) {
|
||||
return function ($scope, element, attrs, ngModel) {
|
||||
$(element).sortable({
|
||||
axis: "y",
|
||||
start: function (event, ui) {
|
||||
ui.item.data('startIndex', ui.item.index());
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
var taskType = angular.element(ui.item[0]).scope().task.type + 's'
|
||||
var startIndex = ui.item.data('startIndex');
|
||||
var task = User.user[taskType][startIndex];
|
||||
User.log({op: 'sortTask', task: task, from: startIndex, to: ui.item.index()});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,27 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The authentication controller (login & facebook)
|
||||
*
|
||||
*/
|
||||
|
||||
habitrpg.controller('AuthCtrl', function AuthCtrl($scope, Facebook, LocalAuth, User, $http, $location) {
|
||||
$scope.Facebook = Facebook;
|
||||
$scope.Local = LocalAuth;
|
||||
|
||||
$scope.uuid = ''
|
||||
$scope.apiToken = ''
|
||||
|
||||
$scope.apiLogin = function() {
|
||||
|
||||
User.authenticate($scope.uuid, $scope.apiToken, function(err) {
|
||||
if (!err) {
|
||||
alert('Login succesfull!');
|
||||
$location.path("/habit");
|
||||
User.fetch()
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The character controller:
|
||||
*
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'CharacterCtrl', function CharacterCtrl( $scope, $location, filterFilter, User ) {
|
||||
|
||||
$scope.user = User.user;
|
||||
|
||||
$scope.equipped = function(user, type) {
|
||||
return window.habitrpgShared.helpers.equipped(user, type);
|
||||
}
|
||||
|
||||
$scope.$watch('user.tasks', function(){
|
||||
$scope.hpPercent = function(hp) {
|
||||
return (hp / 50) * 100;
|
||||
}
|
||||
|
||||
$scope.expPercent = function(exp, level) {
|
||||
return Math.round((exp / window.habitrpgShared.algos.tnl(level)) * 100);
|
||||
}
|
||||
})
|
||||
|
||||
$scope.showUserAvatar = function() {
|
||||
$('.userAvatar').show()
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Phonegap events
|
||||
*
|
||||
*/
|
||||
|
||||
if (typeof cordova != 'undefined') {
|
||||
// the second parameter is the callback to be called
|
||||
document.addEventListener("online", yourCallbackFunction, false);
|
||||
document.addEventListener("offline", yourCallbackFunction, false);
|
||||
document.addEventListener("resume", yourCallbackFunction, false);
|
||||
document.addEventListener("pause", yourCallbackFunction, false);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The login controller:
|
||||
*
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'LoginCtrl', function CharacterCtrl( $scope, $location, filterFilter, User ) {
|
||||
|
||||
|
||||
});
|
||||
@@ -1,43 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The menu controller:
|
||||
* - sets the menu options, should we do it dynamic so it generates the menu like: width = 1/elements * 100 ?
|
||||
* - exposes the model to the template and provides event handlers
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'MenuCtrl', function MenuCtrl( $scope, $location, filterFilter) {
|
||||
|
||||
var nav = $scope.nav = [
|
||||
|
||||
{
|
||||
'name' :'#habit',
|
||||
'img' :'explorer.png',
|
||||
'link' :'Habits'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#daily',
|
||||
'img' :'contacts.png',
|
||||
'link' :'Dailies'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#todo',
|
||||
'img' :'todo.png',
|
||||
'link' :'Todos'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#reward',
|
||||
'img' :'explorer.png',
|
||||
'link' :'Rewards'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The nav controller:
|
||||
* - sets the menu options, should we do it dynamic so it generates the menu like: width = 1/elements * 100 ?
|
||||
* - exposes the model to the template and provides event handlers
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'NavCtrl', function NavCtrl( $scope, $location, filterFilter ) {
|
||||
var nav = $scope.nav = [
|
||||
|
||||
{
|
||||
'name' :'#habit',
|
||||
'img' :'explorer.png'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#daily',
|
||||
'img' :'contacts.png'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#todo',
|
||||
'img' :'todo.png'
|
||||
},
|
||||
|
||||
{
|
||||
'name' :'#reward',
|
||||
'img' :'explorer.png'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
habitrpg.controller('NotificationCtrl', function ($scope, $location, filterFilter, Notification) {
|
||||
$scope.data = Notification.get();
|
||||
|
||||
$('#notification').bind('touchend.swipe', function (event) {
|
||||
Notification.clearTimer();
|
||||
Notification.hide();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
// Make user and settings available for everyone through root scope.
|
||||
habitrpg.controller( 'RootCtrl', function ( $scope, $rootScope, User) {
|
||||
$rootScope.User = User;
|
||||
$rootScope.user = User.user;
|
||||
$rootScope.settings = User.settings;
|
||||
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
// Make user and settings available for everyone through root scope.
|
||||
habitrpg.controller('SettingsCtrl', function ($scope, User, $location) {
|
||||
$scope.resetApp = function () {
|
||||
localStorage.clear();
|
||||
location.reload();
|
||||
};
|
||||
$scope.auth = function (id, token) {
|
||||
User.authenticate(id, token, function (err) {
|
||||
if (!err) {
|
||||
alert('Login succesfull!');
|
||||
$location.path("/habit");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
habitrpg.controller('TaskDetailsCtrl', function TaskDetailsCtrl($scope, $rootScope, $location, User) {
|
||||
|
||||
$scope.task = $rootScope.selectedTask;
|
||||
$scope.editing = false;
|
||||
$scope.editedTask = null;
|
||||
|
||||
$scope.goBack = function () {
|
||||
$rootScope.selectedTask = null;
|
||||
$location.path('/' + $scope.task.type);
|
||||
};
|
||||
|
||||
$scope.edit = function () {
|
||||
$scope.originalTask = _.clone($scope.task); // TODO deep clone?;
|
||||
$scope.editedTask = $scope.task;
|
||||
$scope.editing = true;
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
var task = $scope.task;
|
||||
User.log([
|
||||
{op: 'set', path: "tasks." + task.id + ".text", value: task.text},
|
||||
{op: 'set', path: "tasks." + task.id + ".notes", value: task.notes}
|
||||
]);
|
||||
$rootScope.selectedTask = null;
|
||||
$location.path('/' + $scope.task.type);
|
||||
$scope.editing = false;
|
||||
};
|
||||
|
||||
$scope.cancel = function () {
|
||||
// reset $scope.task to $scope.originalTask
|
||||
for (var key in $scope.task) {
|
||||
$scope.task[key] = $scope.originalTask[key];
|
||||
}
|
||||
$scope.originalTask = null;
|
||||
$scope.editedTask = null;
|
||||
$scope.editing = false;
|
||||
};
|
||||
|
||||
$scope.delete = function () {
|
||||
var task = $scope.task;
|
||||
var tasks = User.user[task.type+'s'];
|
||||
User.log({op: 'delTask', task: task});
|
||||
$scope.goBack();
|
||||
delete tasks.splice(tasks.indexOf(task),1);
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
@@ -1,305 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
habitrpg.controller('TasksCtrl', function TasksCtrl($scope, $rootScope, $location, filterFilter, User, Algos, Helpers, Notification) {
|
||||
|
||||
$scope.user = User.user;
|
||||
|
||||
$scope.$watch('User.user.stats.gp', function() {
|
||||
$scope.money_gold = Math.round(User.user.stats.gp)
|
||||
})
|
||||
|
||||
$scope.taskTypeTitle = function () {
|
||||
// show title according to the location
|
||||
switch ($location.path().split('/')[1]) {
|
||||
case 'habit':
|
||||
return 'Habits';
|
||||
case 'daily':
|
||||
return 'Dailies';
|
||||
case 'todo':
|
||||
return 'Todos';
|
||||
case 'reward':
|
||||
return 'Rewards';
|
||||
default :
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
$scope.taskTypeTitleSingular = function () {
|
||||
// show title according to the location, singular form
|
||||
return $scope.taskTypeTitle().slice(0,-1);
|
||||
};
|
||||
|
||||
$scope.taskType = function () {
|
||||
return $location.path().split('/')[1]
|
||||
};
|
||||
|
||||
$scope.tasks = function () {
|
||||
//return task array based on our location i.e. /habit will return user.habits[]
|
||||
var tasks = []
|
||||
//return User.user[$scope.taskType() + 's']
|
||||
|
||||
_.each(User.user['habits'], function(el, index) {
|
||||
tasks.push(el)
|
||||
})
|
||||
|
||||
_.each(User.user['dailys'], function(el, index) {
|
||||
tasks.push(el)
|
||||
})
|
||||
|
||||
_.each(User.user['todos'], function(el, index) {
|
||||
tasks.push(el)
|
||||
})
|
||||
|
||||
_.each(User.user['rewards'], function(el, index) {
|
||||
tasks.push(el)
|
||||
})
|
||||
|
||||
return tasks
|
||||
};
|
||||
|
||||
$scope.taskFilter = function (task) {
|
||||
return ($location.path() == '/todo') ? !task.completed :
|
||||
($location.path() == '/todo/completed') ? task.completed :
|
||||
true;
|
||||
};
|
||||
|
||||
$scope.score = function (task, direction) {
|
||||
//save current stats to compute the difference after scoring.
|
||||
var statsDiff = {};
|
||||
var oldStats = _.clone(User.user.stats);
|
||||
|
||||
Algos.score(User.user, task, direction);
|
||||
|
||||
//compute the stats change.
|
||||
_.each(oldStats, function (value, key) {
|
||||
var newValue = User.user.stats[key];
|
||||
if (newValue !== value) {
|
||||
statsDiff[key] = newValue - value;
|
||||
}
|
||||
});
|
||||
//notify user if there are changes in stats.
|
||||
if (Object.keys(statsDiff).length > 0) {
|
||||
// Notification.push({type: 'stats', stats: statsDiff});
|
||||
}
|
||||
User.log({op: 'score', task: task, dir: direction});
|
||||
};
|
||||
|
||||
$scope.getClass = function(task) {
|
||||
var out = ''
|
||||
if (task.type == 'daily' && task.completed)
|
||||
out += ' completed'
|
||||
else if (task.value < -20)
|
||||
out += ' color-worst'
|
||||
else if (task.value < -10)
|
||||
out += ' color-worse'
|
||||
else if (task.value < -1)
|
||||
out += ' color-bad'
|
||||
else if (task.value < 1)
|
||||
out += ' color-neutral'
|
||||
else if (task.value < 5)
|
||||
out += ' color-good'
|
||||
else if (task.value < 10)
|
||||
out += ' color-better'
|
||||
else
|
||||
out += ' color-best'
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
$scope.addTask = function (type) {
|
||||
var task = null
|
||||
|
||||
if (type == 'habit') {
|
||||
task = $scope.newTaskHabit
|
||||
}else if (type == 'daily') {
|
||||
task = $scope.newTaskDailies
|
||||
}else if (type == 'todo') {
|
||||
task = $scope.newTaskTodo
|
||||
}else if (type == 'reward') {
|
||||
task = $scope.newTaskReward
|
||||
}
|
||||
|
||||
if (!task.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var defaults = {
|
||||
text: task,
|
||||
type: type,
|
||||
value: type == 'reward' ? 20 : 0
|
||||
},
|
||||
extra = {};
|
||||
|
||||
switch (type) {
|
||||
case 'habit':
|
||||
extra = {up: true, down: true};
|
||||
break;
|
||||
case 'daily':
|
||||
case 'todo':
|
||||
extra = {completed: false};
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
var newTask = _.defaults(extra, defaults);
|
||||
newTask.id = Helpers.uuid();
|
||||
User.user[newTask.type + 's'].unshift(newTask)
|
||||
$scope.newTask = '';
|
||||
User.log({op: 'addTask', task: newTask});
|
||||
|
||||
//Add the new task to the actions log
|
||||
|
||||
};
|
||||
|
||||
$scope.delTask = function(taskObj) {
|
||||
User.log({op:'delTask', task:taskObj})
|
||||
}
|
||||
|
||||
$scope.clearDoneTodos = function () {
|
||||
//We can't alter $scope.user.tasks here. We have to invoke API call.
|
||||
//To be implemented
|
||||
};
|
||||
|
||||
$scope.selectTask = function (task) {
|
||||
$rootScope.selectedTask = task;
|
||||
$location.path('/tasks/' + task.id)
|
||||
}
|
||||
|
||||
$scope.changeCheck = function (task) {
|
||||
// This is calculated post-change, so task.completed=true if they just checked it
|
||||
if (task.completed) {
|
||||
$scope.score(task, 'up')
|
||||
} else {
|
||||
$scope.score(task, 'down')
|
||||
}
|
||||
}
|
||||
|
||||
$scope.editTask = function(task) {
|
||||
if (!task.editing) {
|
||||
task.editing = true
|
||||
if (typeof task.tags == 'undefined') {
|
||||
task.tags = {}
|
||||
}
|
||||
}else{
|
||||
task.editing = false
|
||||
}
|
||||
}
|
||||
|
||||
$scope.save = function(task) {
|
||||
|
||||
var ops = ([
|
||||
{op: 'set', path: "tasks." + task.id + ".text", value: task.text},
|
||||
{op: 'set', path: "tasks." + task.id + ".notes", value: task.notes},
|
||||
{op: 'set', path: "tasks." + task.id + ".up", value: task.up},
|
||||
{op: 'set', path: "tasks." + task.id + ".down", value: task.down},
|
||||
{op: 'set', path: "tasks." + task.id + ".priority", value: task.priority},
|
||||
{op: 'set', path: "tasks." + task.id + ".date", value: task.date},
|
||||
{op: 'set', path: "tasks." + task.id + ".price", value: task.price},
|
||||
])
|
||||
|
||||
_.each(task.tags, function(el, key, list) {
|
||||
ops.push({op: 'set', path: "tasks." + task.id + ".tags." + key, value: el})
|
||||
})
|
||||
|
||||
_.each(task.repeat, function(el, key, list) {
|
||||
ops.push({op: 'set', path: "tasks." + task.id + ".repeat." + key, value: el})
|
||||
})
|
||||
|
||||
User.log(ops)
|
||||
|
||||
task.editing = false
|
||||
|
||||
}
|
||||
|
||||
$scope.showAdvancedOptions = function(task) {
|
||||
if (!task.advanced) {
|
||||
task.advanced = true
|
||||
}else{
|
||||
task.advanced = false
|
||||
}
|
||||
}
|
||||
|
||||
$scope.setPriority = function(task, priority) {
|
||||
task.priority = priority
|
||||
}
|
||||
|
||||
$scope.getPriority = function(task, priority) {
|
||||
if (task.priority == priority) {
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.getRepeat = function(task, repeat) {
|
||||
var enabled = '';
|
||||
_.each(task.repeat, function(el, key, list) {
|
||||
if (key == repeat && el == true) {
|
||||
enabled = true
|
||||
}
|
||||
})
|
||||
|
||||
if (enabled) {
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
$scope.setRepeat = function(task, repeat) {
|
||||
|
||||
if (typeof task.repeat == 'undefined') {
|
||||
var obj = {}
|
||||
obj[repeat] = true;
|
||||
|
||||
task.repeat = {}
|
||||
task.repeat = obj
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
if (!task.repeat[repeat]) {
|
||||
task.repeat[repeat] = true
|
||||
}else{
|
||||
task.repeat[repeat] = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.addTag = function(task, tag) {
|
||||
var obj = {}
|
||||
obj[tag] = true
|
||||
task.tags.push(obj)
|
||||
}
|
||||
|
||||
$scope.toggleTag = function(task, tag) {
|
||||
var obj = {}
|
||||
if (typeof task.tags != 'undefined') {
|
||||
if (!task.tags[tag]) {
|
||||
task.tags[tag] = false;
|
||||
}else{
|
||||
task.tags[tag] = true
|
||||
}
|
||||
}else{
|
||||
task.tags = {}
|
||||
task.tags[tag] = true
|
||||
}
|
||||
}
|
||||
|
||||
$scope.deleteTask = function(task) {
|
||||
var info = confirm('Are you sure you want to delete this task ?')
|
||||
|
||||
if (info == true) {
|
||||
|
||||
_.each(User.user[task.type + 's'], function(el, index) {
|
||||
if (el.id == task.id) {
|
||||
User.user[task.type + 's'].splice(index, 1)
|
||||
}
|
||||
})
|
||||
|
||||
User.log({op:'delTask', task:task})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The character controller:
|
||||
*
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'userAvatarCtrl', function CharacterCtrl( $scope, $location, filterFilter, User ) {
|
||||
|
||||
$scope.user = User.user;
|
||||
|
||||
$scope.changeHair = function(color) {
|
||||
User.user.preferences.hair = color;
|
||||
User.log({op:"set",path:"preferences.hair",value:color})
|
||||
}
|
||||
|
||||
$scope.changeSkin = function(color) {
|
||||
User.user.preferences.skin = color
|
||||
User.log({op:"set",path:"preferences.skin",value:color})
|
||||
}
|
||||
|
||||
$scope.changeSex = function(gender) {
|
||||
User.user.preferences.gender = gender
|
||||
User.log({op:"set",path:"preferences.gender",value:gender})
|
||||
}
|
||||
|
||||
$scope.changeArmor = function(set) {
|
||||
User.user.preferences.armorSet = v
|
||||
User.log({op:"set",path:"preferences.armorSet",value:set})
|
||||
}
|
||||
|
||||
$scope.hideUserAvatar = function() {
|
||||
$('.userAvatar').hide()
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The nav controller:
|
||||
* - sets the menu options, should we do it dynamic so it generates the menu like: width = 1/elements * 100 ?
|
||||
* - exposes the model to the template and provides event handlers
|
||||
*/
|
||||
|
||||
habitrpg.controller( 'WrapperCtrl', function WrapperCtrl( $scope, $location, filterFilter, Facebook ) {
|
||||
|
||||
|
||||
$scope.showMenu = function() {
|
||||
|
||||
if ($location.path() == '/options') {
|
||||
$location.path('/')
|
||||
}else{
|
||||
$location.path('/options')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.logout = function() {
|
||||
localStorage.clear()
|
||||
$location.path('login')
|
||||
location.reload()
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Directive that executes an expression when the element it is applied to loses focus.
|
||||
*/
|
||||
habitrpg.directive('taskBlur', function() {
|
||||
return function( scope, elem, attrs ) {
|
||||
elem.bind('blur', function() {
|
||||
scope.$apply(attrs.taskBlur);
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Directive that places focus on the element it is applied to when the expression it binds to evaluates to true.
|
||||
*/
|
||||
habitrpg.directive('taskFocus', function( $timeout ) {
|
||||
return function( scope, elem, attrs ) {
|
||||
scope.$watch(attrs.taskFocus, function( newval ) {
|
||||
if ( newval ) {
|
||||
$timeout(function() {
|
||||
elem[0].focus();
|
||||
}, 0, false);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
angular.module('habitrpg')
|
||||
.filter('gold', function () {
|
||||
return function (gp) {
|
||||
return Math.floor(gp);
|
||||
}
|
||||
}).filter('silver', function () {
|
||||
return function (gp) {
|
||||
return Math.floor((gp - Math.floor(gp))*100);
|
||||
}
|
||||
});
|
||||
@@ -1,98 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Services that persists and retrieves user from localStorage.
|
||||
*/
|
||||
|
||||
var facebook = {}
|
||||
|
||||
angular.module('authServices', ['userServices']).
|
||||
factory('Facebook', function($http, User) {
|
||||
//TODO FB.init({appId: '${section.parameters['facebook.app.id']}', status: true, cookie: true, xfbml: true});
|
||||
var auth, user = User.user;
|
||||
|
||||
facebook.handleStatusChange = function(session) {
|
||||
if (session.authResponse) {
|
||||
|
||||
FB.api('/me', {
|
||||
fields: 'name, picture, email'
|
||||
}, function(response) {
|
||||
console.log(response.error)
|
||||
if (!response.error) {
|
||||
|
||||
var data = {
|
||||
name: response.name,
|
||||
facebook_id: response.id,
|
||||
email: response.email
|
||||
}
|
||||
|
||||
$http.post('http://127.0.0.1:3000/api/v1/user/auth/facebook', data).success(function(data, status, headers, config) {
|
||||
User.authenticate(data.id, data.token, function(err) {
|
||||
if (!err) {
|
||||
alert('Login succesfull!');
|
||||
$location.path("/habit");
|
||||
}
|
||||
});
|
||||
}).error(function(response) {
|
||||
console.log('error')
|
||||
})
|
||||
|
||||
} else {
|
||||
alert('napaka')
|
||||
}
|
||||
//clearAction();
|
||||
});
|
||||
} else {
|
||||
document.body.className = 'not_connected';
|
||||
//clearAction();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
authUser: function() {
|
||||
FB.Event.subscribe('auth.statusChange', facebook.handleStatusChange);
|
||||
},
|
||||
|
||||
getAuth: function() {
|
||||
return auth;
|
||||
},
|
||||
|
||||
login: function() {
|
||||
|
||||
FB.login(null, {
|
||||
scope: 'email'
|
||||
});
|
||||
},
|
||||
|
||||
logout: function() {
|
||||
FB.logout(function(response) {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
.factory('LocalAuth', function($http, User) {
|
||||
|
||||
var auth, user = User.user;
|
||||
|
||||
return {
|
||||
|
||||
getAuth: function() {
|
||||
return auth;
|
||||
},
|
||||
|
||||
login: function() {
|
||||
user.id = '';
|
||||
user.apiToken = '';
|
||||
User.authenticate();
|
||||
return;
|
||||
|
||||
},
|
||||
|
||||
logout: function() {}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Services that persists and retrieves user from localStorage.
|
||||
*/
|
||||
|
||||
angular.module('sharedServices', [] ).
|
||||
factory("Items", function($rootScope){
|
||||
return window.habitrpgShared.items;
|
||||
}).
|
||||
factory("Algos", function($rootScope){
|
||||
return window.habitrpgShared.algos;
|
||||
}).
|
||||
factory("Helpers", function($rootScope){
|
||||
return window.habitrpgShared.helpers;
|
||||
});
|
||||
@@ -1,212 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Services that persists and retrieves user from localStorage.
|
||||
*/
|
||||
|
||||
angular.module('userServices', []).
|
||||
factory('User', function($http, $location, $rootScope, $timeout) {
|
||||
var STORAGE_ID = 'habitrpg-user',
|
||||
HABIT_MOBILE_SETTINGS = 'habit-mobile-settings',
|
||||
authenticated = false,
|
||||
defaultSettings = {
|
||||
auth: {
|
||||
apiId: '',
|
||||
apiToken: ''
|
||||
},
|
||||
sync: {
|
||||
queue: [],
|
||||
//here OT will be queued up, this is NOT call-back queue!
|
||||
sent: [] //here will be OT which have been sent, but we have not got reply from server yet.
|
||||
},
|
||||
fetching: false,
|
||||
// whether fetch() was called or no. this is to avoid race conditions
|
||||
online: false
|
||||
},
|
||||
settings = {},
|
||||
//habit mobile settings (like auth etc.) to be stored here
|
||||
URL = 'https://beta.habitrpg.com/api/v1/user/batch-update',
|
||||
schema = {
|
||||
stats: {
|
||||
gp: 0,
|
||||
exp: 0,
|
||||
lvl: 1,
|
||||
hp: 50
|
||||
},
|
||||
party: {
|
||||
current: null,
|
||||
invitation: null
|
||||
},
|
||||
items: {
|
||||
weapon: 0,
|
||||
armor: 0,
|
||||
head: 0,
|
||||
shield: 0,
|
||||
pets: [],
|
||||
eggs: []
|
||||
},
|
||||
preferences: {
|
||||
gender: 'm',
|
||||
skin: 'white',
|
||||
hair: 'blond',
|
||||
armorSet: 'v1'
|
||||
},
|
||||
auth: {
|
||||
timestamps: {
|
||||
savedAt: +new Date
|
||||
}
|
||||
},
|
||||
tasks: [],
|
||||
habits:[],
|
||||
dailys:[],
|
||||
rewards:[],
|
||||
todos:[],
|
||||
// note task-types are differentiated / filtered by type {habit, daily, todo, reward}
|
||||
lastCron: 'new',
|
||||
balance: 1,
|
||||
flags: {}
|
||||
},
|
||||
user = {}; // this is stored as a reference accessible to all controllers, that way updates propagate
|
||||
|
||||
var syncQueue = function(cb) {
|
||||
if (!authenticated) {
|
||||
alert("Not authenticated, can't sync, go to settings first.");
|
||||
return;
|
||||
}
|
||||
|
||||
var queue = settings.sync.queue;
|
||||
var sent = settings.sync.sent;
|
||||
if (queue.length === 0) {
|
||||
console.log('Sync: Queue is empty');
|
||||
return;
|
||||
}
|
||||
if (settings.fetching) {
|
||||
console.log('Sync: Already fetching');
|
||||
return;
|
||||
}
|
||||
if (settings.online !== true) {
|
||||
console.log('Sync: Not online');
|
||||
return;
|
||||
}
|
||||
|
||||
settings.fetching = true;
|
||||
// move all actions from queue array to sent array
|
||||
_.times(queue.length, function() {
|
||||
sent.push(queue.shift());
|
||||
});
|
||||
|
||||
$http.post(URL, sent).success(function(data, status, heacreatingders, config) {
|
||||
data.tasks = _.toArray(data.tasks);
|
||||
//make sure there are no pending actions to sync. If there are any it is not safe to apply model from server as we may overwrite user data.
|
||||
|
||||
sent.length = 0;
|
||||
settings.fetching = false;
|
||||
save();
|
||||
if (cb) {
|
||||
cb(false)
|
||||
}
|
||||
|
||||
syncQueue(); // call syncQueue to check if anyone pushed more actions to the queue while we were talking to server.
|
||||
}).error(function(data, status, headers, config) {
|
||||
//move sent actions back to queue
|
||||
_.times(sent.length, function() {
|
||||
queue.push(sent.shift())
|
||||
});
|
||||
settings.fetching = false;
|
||||
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
var fetch = function() {
|
||||
$http.post(URL, {})
|
||||
.success(function(response) {
|
||||
_.extend(user,response)
|
||||
})
|
||||
}
|
||||
var save = function() {
|
||||
localStorage.setItem(STORAGE_ID, JSON.stringify(user));
|
||||
localStorage.setItem(HABIT_MOBILE_SETTINGS, JSON.stringify(settings));
|
||||
};
|
||||
var userServices = {
|
||||
user: user,
|
||||
online: function(status) {
|
||||
if (status === true) {
|
||||
settings.online = true;
|
||||
syncQueue();
|
||||
} else {
|
||||
settings.online = false;
|
||||
};
|
||||
},
|
||||
|
||||
authenticate: function(apiId, apiToken, cb) {
|
||||
if ( !! apiId && !! apiToken) {
|
||||
$http.defaults.headers.common = {
|
||||
'Content-Type': "application/json;charset=utf-8"
|
||||
};
|
||||
$http.defaults.headers.common['x-api-user'] = apiId;
|
||||
$http.defaults.headers.common['x-api-key'] = apiToken;
|
||||
authenticated = true;
|
||||
settings.auth.apiId = apiId;
|
||||
settings.auth.apiToken = apiToken;
|
||||
settings.online = true;
|
||||
this.log({}, cb);
|
||||
} else {
|
||||
alert('Please enter your ID and Token in settings.')
|
||||
}
|
||||
},
|
||||
|
||||
log: function(action, cb) {
|
||||
//push by one buy one if an array passed in.
|
||||
if (_.isArray(action)) {
|
||||
action.forEach(function(a) {
|
||||
settings.sync.queue.push(a);
|
||||
});
|
||||
} else {
|
||||
settings.sync.queue.push(action);
|
||||
}
|
||||
|
||||
save();
|
||||
syncQueue(cb);
|
||||
|
||||
|
||||
},
|
||||
fetch:fetch,
|
||||
settings: settings
|
||||
};
|
||||
|
||||
|
||||
//load settings if we have them
|
||||
if (localStorage.getItem(HABIT_MOBILE_SETTINGS)) {
|
||||
//use extend here to make sure we keep object reference in other angular controllers
|
||||
_.extend(settings, JSON.parse(localStorage.getItem(HABIT_MOBILE_SETTINGS)));
|
||||
|
||||
//if settings were saved while fetch was in process reset the flag.
|
||||
settings.fetching = false;
|
||||
//create and load if not
|
||||
} else {
|
||||
localStorage.setItem(HABIT_MOBILE_SETTINGS, JSON.stringify(defaultSettings));
|
||||
_.extend(settings, defaultSettings);
|
||||
}
|
||||
|
||||
//If user does not have ApiID that forward him to settings.
|
||||
if (!settings.auth.apiId || !settings.auth.apiToken) {
|
||||
$location.path("/login");
|
||||
} else {
|
||||
userServices.authenticate(settings.auth.apiId, settings.auth.apiToken)
|
||||
}
|
||||
|
||||
fetch()
|
||||
|
||||
//first we populate user with schema
|
||||
_.extend(user, schema);
|
||||
|
||||
//than we try to load localStorage
|
||||
if (localStorage.getItem(STORAGE_ID)) {
|
||||
_.extend(user, JSON.parse(localStorage.getItem(STORAGE_ID)));
|
||||
}
|
||||
|
||||
return userServices;
|
||||
|
||||
});
|
||||
@@ -1,58 +0,0 @@
|
||||
CDV = ( typeof CDV == 'undefined' ? {} : CDV );
|
||||
var cordova = window.cordova || window.Cordova;
|
||||
CDV.FB = {
|
||||
init: function(apiKey, fail) {
|
||||
// create the fb-root element if it doesn't exist
|
||||
if (!document.getElementById('fb-root')) {
|
||||
var elem = document.createElement('div');
|
||||
elem.id = 'fb-root';
|
||||
document.body.appendChild(elem);
|
||||
}
|
||||
cordova.exec(function() {
|
||||
var authResponse = JSON.parse(localStorage.getItem('cdv_fb_session') || '{"expiresIn":0}');
|
||||
if (authResponse && authResponse.expirationTime) {
|
||||
var nowTime = (new Date()).getTime();
|
||||
if (authResponse.expirationTime > nowTime) {
|
||||
// Update expires in information
|
||||
updatedExpiresIn = Math.floor((authResponse.expirationTime - nowTime) / 1000);
|
||||
authResponse.expiresIn = updatedExpiresIn;
|
||||
|
||||
localStorage.setItem('cdv_fb_session', JSON.stringify(authResponse));
|
||||
FB.Auth.setAuthResponse(authResponse, 'connected');
|
||||
}
|
||||
}
|
||||
console.log('Cordova Facebook Connect plugin initialized successfully.');
|
||||
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'init', [apiKey]);
|
||||
},
|
||||
login: function(params, cb, fail) {
|
||||
params = params || { scope: '' };
|
||||
cordova.exec(function(e) { // login
|
||||
if (e.authResponse && e.authResponse.expiresIn) {
|
||||
var expirationTime = e.authResponse.expiresIn === 0
|
||||
? 0
|
||||
: (new Date()).getTime() + e.authResponse.expiresIn * 1000;
|
||||
e.authResponse.expirationTime = expirationTime;
|
||||
}
|
||||
localStorage.setItem('cdv_fb_session', JSON.stringify(e.authResponse));
|
||||
FB.Auth.setAuthResponse(e.authResponse, 'connected');
|
||||
if (cb) cb(e);
|
||||
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'login', params.scope.split(',') );
|
||||
},
|
||||
logout: function(cb, fail) {
|
||||
cordova.exec(function(e) {
|
||||
localStorage.removeItem('cdv_fb_session');
|
||||
FB.Auth.setAuthResponse(null, 'notConnected');
|
||||
if (cb) cb(e);
|
||||
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'logout', []);
|
||||
},
|
||||
getLoginStatus: function(cb, fail) {
|
||||
cordova.exec(function(e) {
|
||||
if (cb) cb(e);
|
||||
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'getLoginStatus', []);
|
||||
},
|
||||
dialog: function(params, cb, fail) {
|
||||
cordova.exec(function(e) { // login
|
||||
if (cb) cb(e);
|
||||
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'showDialog', [params] );
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,377 +0,0 @@
|
||||
var traverse = require('traverse');
|
||||
var Stream = require('stream').Stream;
|
||||
var charm = require('charm');
|
||||
var deepEqual = require('deep-is');
|
||||
|
||||
var exports = module.exports = function (opts_) {
|
||||
var fn = difflet.bind(null, opts_);
|
||||
fn.compare = function (prev, next) {
|
||||
var opts = Object.keys(opts_ || {}).reduce(function (acc, key) {
|
||||
acc[key] = opts_[key];
|
||||
return acc;
|
||||
}, {});
|
||||
var s = opts.stream = new Stream;
|
||||
var data = '';
|
||||
s.write = function (buf) { data += buf };
|
||||
s.end = function () {};
|
||||
s.readable = true;
|
||||
s.writable = true;
|
||||
|
||||
difflet(opts, prev, next);
|
||||
return data;
|
||||
};
|
||||
return fn;
|
||||
};
|
||||
|
||||
exports.compare = function (prev, next) {
|
||||
return exports({}).compare(prev, next);
|
||||
};
|
||||
|
||||
function difflet (opts, prev, next) {
|
||||
var stream = opts.stream || new Stream;
|
||||
if (!opts.stream) {
|
||||
stream.readable = true;
|
||||
stream.writable = true;
|
||||
stream.write = function (buf) { this.emit('data', buf) };
|
||||
stream.end = function () { this.emit('end') };
|
||||
}
|
||||
|
||||
if (!opts) opts = {};
|
||||
if (opts.start === undefined && opts.stop === undefined) {
|
||||
var c = charm(stream);
|
||||
opts.start = function (type) {
|
||||
c.foreground({
|
||||
inserted : 'green',
|
||||
updated : 'blue',
|
||||
deleted : 'red',
|
||||
comment : 'cyan',
|
||||
}[type]);
|
||||
c.display('bright');
|
||||
};
|
||||
opts.stop = function (type) {
|
||||
c.display('reset');
|
||||
};
|
||||
}
|
||||
var write = function (buf) {
|
||||
if (opts.write) opts.write(buf, stream)
|
||||
else stream.write(buf)
|
||||
};
|
||||
|
||||
var commaFirst = opts.comma === 'first';
|
||||
|
||||
var stringify = function (node, params) {
|
||||
return stringifier.call(this, true, node, params || opts);
|
||||
};
|
||||
var plainStringify = function (node, params) {
|
||||
return stringifier.call(this, false, node, params || opts);
|
||||
};
|
||||
|
||||
var levels = 0;
|
||||
function set (type) {
|
||||
if (levels === 0) opts.start(type, stream);
|
||||
levels ++;
|
||||
}
|
||||
|
||||
function unset (type) {
|
||||
if (--levels === 0) opts.stop(type, stream);
|
||||
}
|
||||
|
||||
function stringifier (insertable, node, opts) {
|
||||
var indent = opts.indent;
|
||||
|
||||
if (insertable) {
|
||||
var prevNode = traverse.get(prev, this.path || []);
|
||||
}
|
||||
var inserted = insertable && prevNode === undefined;
|
||||
|
||||
var indentx;
|
||||
try {
|
||||
indentx = indent ? Array(
|
||||
((this.path || []).length + 1) * indent + 1
|
||||
).join(' ') : '';
|
||||
} catch (e) {
|
||||
// at times we get an invalid Array size here and need to prevent crashing
|
||||
indentx = '';
|
||||
}
|
||||
if (commaFirst) indentx = indentx.slice(indent);
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
var updated = (prevNode || traverse.has(prev, this.path))
|
||||
&& !Array.isArray(prevNode);
|
||||
if (updated) {
|
||||
set('updated');
|
||||
}
|
||||
|
||||
if (opts.comment && !Array.isArray(prevNode)) {
|
||||
indent = 0;
|
||||
}
|
||||
|
||||
this.before(function () {
|
||||
if (inserted) set('inserted');
|
||||
if (indent && commaFirst) {
|
||||
if ((this.path || []).length === 0
|
||||
|| Array.isArray(this.parent.node)) {
|
||||
write('[ ');
|
||||
}
|
||||
else write('\n' + indentx + '[ ');
|
||||
}
|
||||
else if (indent) {
|
||||
write('[\n' + indentx);
|
||||
}
|
||||
else {
|
||||
write('[');
|
||||
}
|
||||
});
|
||||
|
||||
this.post(function (child) {
|
||||
if (!child.isLast && !(indent && commaFirst)) {
|
||||
write(',');
|
||||
}
|
||||
|
||||
var prev = prevNode && prevNode[child.key];
|
||||
if (indent && opts.comment && child.node !== prev
|
||||
&& (typeof child.node !== 'object' || typeof prev !== 'object')
|
||||
) {
|
||||
set('comment');
|
||||
write(' // != ');
|
||||
traverse(prev).forEach(function (x) {
|
||||
plainStringify.call(this, x, { indent : 0 });
|
||||
});
|
||||
unset('comment');
|
||||
}
|
||||
|
||||
if (!child.isLast) {
|
||||
if (indent && commaFirst) {
|
||||
write('\n' + indentx + ', ');
|
||||
}
|
||||
else if (indent) {
|
||||
write('\n' + indentx);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.after(function () {
|
||||
if (indent && commaFirst) write('\n' + indentx);
|
||||
else if (indent) write('\n' + indentx.slice(indent));
|
||||
|
||||
write(']');
|
||||
if (updated) unset('updated');
|
||||
if (inserted) unset('inserted');
|
||||
});
|
||||
}
|
||||
else if (isRegExp(node)) {
|
||||
this.block();
|
||||
|
||||
if (inserted) {
|
||||
set('inserted');
|
||||
write(node.toString());
|
||||
unset('inserted');
|
||||
}
|
||||
else if (insertable && prevNode !== node) {
|
||||
set('updated');
|
||||
write(node.toString());
|
||||
unset('updated');
|
||||
}
|
||||
else write(node.toString());
|
||||
}
|
||||
else if (typeof node === 'object'
|
||||
&& node && typeof node.inspect === 'function') {
|
||||
this.block();
|
||||
if (inserted) {
|
||||
set('inserted');
|
||||
write(node.inspect());
|
||||
unset('inserted');
|
||||
}
|
||||
else if (!(prevNode && typeof prevNode.inspect === 'function'
|
||||
&& prevNode.inspect() === node.inspect())) {
|
||||
set('updated');
|
||||
write(node.inspect());
|
||||
unset('updated');
|
||||
}
|
||||
else write(node.inspect());
|
||||
}
|
||||
else if (typeof node == 'object' && node !== null) {
|
||||
var insertedKey = false;
|
||||
var deleted = insertable && typeof prevNode === 'object' && prevNode
|
||||
? Object.keys(prevNode).filter(function (key) {
|
||||
return !Object.hasOwnProperty.call(node, key);
|
||||
})
|
||||
: []
|
||||
;
|
||||
|
||||
this.before(function () {
|
||||
if (inserted) set('inserted');
|
||||
write(indent && commaFirst && !this.isRoot
|
||||
? '\n' + indentx + '{ '
|
||||
: '{'
|
||||
);
|
||||
});
|
||||
|
||||
this.pre(function (x, key) {
|
||||
if (insertable) {
|
||||
var obj = traverse.get(prev, this.path.concat(key));
|
||||
if (obj === undefined) {
|
||||
insertedKey = true;
|
||||
set('inserted');
|
||||
}
|
||||
}
|
||||
|
||||
if (indent && !commaFirst) write('\n' + indentx);
|
||||
|
||||
plainStringify(key);
|
||||
write(indent ? ' : ' : ':');
|
||||
});
|
||||
|
||||
this.post(function (child) {
|
||||
if (!child.isLast && !(indent && commaFirst)) {
|
||||
write(',');
|
||||
}
|
||||
|
||||
if (child.isLast && deleted.length) {
|
||||
if (insertedKey) unset('inserted');
|
||||
insertedKey = false;
|
||||
}
|
||||
else if (insertedKey) {
|
||||
unset('inserted');
|
||||
insertedKey = false;
|
||||
}
|
||||
|
||||
var prev = prevNode && prevNode[child.key];
|
||||
if (indent && opts.comment && child.node !== prev
|
||||
&& (typeof child.node !== 'object' || typeof prev !== 'object')
|
||||
) {
|
||||
set('comment');
|
||||
write(' // != ');
|
||||
traverse(prev).forEach(function (x) {
|
||||
plainStringify.call(this, x, { indent : 0 });
|
||||
});
|
||||
unset('comment');
|
||||
}
|
||||
|
||||
if (child.isLast && deleted.length) {
|
||||
if (insertedKey) unset('inserted');
|
||||
insertedKey = false;
|
||||
|
||||
if (indent && commaFirst) {
|
||||
write('\n' + indentx + ', ')
|
||||
}
|
||||
else if (opts.comment && indent) {
|
||||
write('\n' + indentx);
|
||||
}
|
||||
else if (indent) {
|
||||
write(',\n' + indentx);
|
||||
}
|
||||
else write(',');
|
||||
}
|
||||
else {
|
||||
if (!child.isLast) {
|
||||
if (indent && commaFirst) {
|
||||
write('\n' + indentx + ', ');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.after(function () {
|
||||
if (inserted) unset('inserted');
|
||||
|
||||
if (deleted.length) {
|
||||
if (indent && !commaFirst
|
||||
&& Object.keys(node).length === 0) {
|
||||
write('\n' + indentx);
|
||||
}
|
||||
|
||||
set('deleted');
|
||||
deleted.forEach(function (key, ix) {
|
||||
if (indent && opts.comment) {
|
||||
unset('deleted');
|
||||
set('comment');
|
||||
write('// ');
|
||||
unset('comment');
|
||||
set('deleted');
|
||||
}
|
||||
|
||||
plainStringify(key);
|
||||
write(indent ? ' : ' : ':');
|
||||
traverse(prevNode[key]).forEach(function (x) {
|
||||
plainStringify.call(this, x, { indent : 0 });
|
||||
});
|
||||
|
||||
var last = ix === deleted.length - 1;
|
||||
if (insertable && !last) {
|
||||
if (indent && commaFirst) {
|
||||
write('\n' + indentx + ', ');
|
||||
}
|
||||
else if (indent) {
|
||||
write(',\n' + indentx);
|
||||
}
|
||||
else write(',');
|
||||
}
|
||||
});
|
||||
unset('deleted');
|
||||
}
|
||||
|
||||
if (commaFirst && indent) {
|
||||
write(indentx.slice(indent) + ' }');
|
||||
}
|
||||
else if (indent) {
|
||||
write('\n' + indentx.slice(indent) + '}');
|
||||
}
|
||||
else write('}');
|
||||
});
|
||||
}
|
||||
else {
|
||||
var changed = false;
|
||||
|
||||
if (inserted) set('inserted');
|
||||
else if (insertable && !deepEqual(prevNode, node)) {
|
||||
changed = true;
|
||||
set('updated');
|
||||
}
|
||||
|
||||
if (typeof node === 'string') {
|
||||
write('"' + node.toString().replace(/"/g, '\\"') + '"');
|
||||
}
|
||||
else if (isRegExp(node)) {
|
||||
write(node.toString());
|
||||
}
|
||||
else if (typeof node === 'function') {
|
||||
write(node.name
|
||||
? '[Function: ' + node.name + ']'
|
||||
: '[Function]'
|
||||
);
|
||||
}
|
||||
else if (node === undefined) {
|
||||
write('undefined');
|
||||
}
|
||||
else if (node === null) {
|
||||
write('null');
|
||||
}
|
||||
else {
|
||||
write(node.toString());
|
||||
}
|
||||
|
||||
if (inserted) unset('inserted');
|
||||
else if (changed) unset('updated');
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.stream) {
|
||||
traverse(next).forEach(stringify);
|
||||
}
|
||||
else process.nextTick(function () {
|
||||
traverse(next).forEach(stringify);
|
||||
stream.emit('end');
|
||||
});
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
function isRegExp (node) {
|
||||
return node instanceof RegExp || (node
|
||||
&& typeof node.test === 'function'
|
||||
&& typeof node.exec === 'function'
|
||||
&& typeof node.compile === 'function'
|
||||
&& node.constructor && node.constructor.name === 'RegExp'
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* swipe 1.0.2 - jQuery UI Widget
|
||||
* https://github.com/sgentile/jquery.swipe
|
||||
* Copyright (c) 2011 Steve Gentile (http://twitter.com/stevemgentile)
|
||||
* Dual licensed under the MIT and GPL licenses
|
||||
*/
|
||||
(function ($) {
|
||||
$.widget("ui.swipe", {
|
||||
options: {
|
||||
minSwipeLength: 65, // the shortest distance the user may swipe - the lower the number the more sensitive
|
||||
minMouseSwipeLength: 300,
|
||||
preventDefault: false, //used on TouchStart - setting this to true would negate things like button press from working, etc...
|
||||
includeMouseSwipe: false //set to true to enable for mouse swipe
|
||||
},
|
||||
|
||||
touchesCount: 0, //number of finders
|
||||
startTouchXPosition: 0, //initial start location x
|
||||
startTouchYPosition: 0, //initial start location x
|
||||
currentXTouchPosition: 0,
|
||||
currentYTouchPosition: 0,
|
||||
swipeLength: 0,
|
||||
previousPosition: {},
|
||||
|
||||
initialXMousePosition: null, //for mouse
|
||||
initialYMousePosition: null, //for mouse
|
||||
|
||||
|
||||
swiped: function (e, ui) { },
|
||||
|
||||
_create: function () {
|
||||
var self = this;
|
||||
var $touch = this.element;
|
||||
|
||||
$touch.bind({
|
||||
"touchstart": function (event) {
|
||||
//http://stackoverflow.com/questions/671498/jquery-live-removing-iphone-touch-event-attributes
|
||||
self.touchStart(event.originalEvent);
|
||||
},
|
||||
"touchmove": function (event) {
|
||||
self.touchMove(event.originalEvent);
|
||||
|
||||
},
|
||||
"touchcancel": function (event) {
|
||||
self.touchCancel(event.originalEvent);
|
||||
},
|
||||
"touchend": function (event) {
|
||||
self.touchEnd(event.originalEvent, function (swipe) {
|
||||
self._trigger("swiped", event, { swipeDirection: swipe });
|
||||
});
|
||||
}
|
||||
});
|
||||
//WIndows 8 touch support
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
debug.info("msPointerEnabled");
|
||||
$touch.on({
|
||||
"MSPointerDown": function (event) {
|
||||
//event.originalEvent.preventMouseEvent();
|
||||
debug.info("MSPointerDown");
|
||||
self.touchStart(event.originalEvent);
|
||||
},
|
||||
"MSPointerMove": function (event) {
|
||||
debug.info("MSPointerMove");
|
||||
self.touchMove(event.originalEvent);
|
||||
|
||||
},
|
||||
"MSPointerOut": function (event) {
|
||||
debug.info("MSPointerOut");
|
||||
self.touchCancel(event.originalEvent);
|
||||
|
||||
},
|
||||
"MSPointerUp": function (event) {
|
||||
debug.info("MSPointerUp");
|
||||
self.touchEnd(event.originalEvent, function (swipe) {
|
||||
debug.info("MSPointerUp touchEnd");
|
||||
self._trigger("swiped", event, { swipeDirection: swipe });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (self.options.includeMouseSwipe) {
|
||||
$touch.bind({
|
||||
"mousedown": function (event) {
|
||||
self.initialXMousePosition = event.pageX;
|
||||
self.initialYMousePosition = event.pageY;
|
||||
//event.stopPropagation();
|
||||
event.preventDefault();
|
||||
},
|
||||
"mouseup": function (event) {
|
||||
var x = event.pageX;
|
||||
var y = event.pageY;
|
||||
//event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
var mouseSwipeLength = self.calculateSwipeAngle(self.initialXMousePosition, x, self.initialYMousePosition, y);
|
||||
// if the user swiped more than the minimum length, perform the appropriate action
|
||||
if (mouseSwipeLength >= self.options.minMouseSwipeLength) {
|
||||
var swipeAngle = self.getSwipeAngle(self.initialXMousePosition, x, self.initialYMousePosition, y);
|
||||
var swipeDirection = self.determineSwipeDirection(swipeAngle);
|
||||
|
||||
if (swipeDirection != null) {
|
||||
self._trigger('swiped', event, { swipeDirection: swipeDirection });
|
||||
}
|
||||
}
|
||||
self.initialXMousePosition = null;
|
||||
self.initialYMousePosition = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
touchStart: function (event) {
|
||||
var self = this;
|
||||
|
||||
if (self.options.preventDefault) {
|
||||
// disable the standard ability to select the touched object
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
var currentPointers = event.getPointerList();
|
||||
debug.info("touchStart touchesCount: " + currentPointers.length);
|
||||
self.touchesCount = currentPointers.length;
|
||||
debug.info('touch start length: ' + currentPointers.length);
|
||||
if (currentPointers.length === 1) {
|
||||
self.startTouchXPosition = event.pageX;
|
||||
self.startTouchYPosition = event.pageY;
|
||||
debug.info("touchstart " + self.startTouchXPosition + " " + self.startTouchYPosition);
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
} else {
|
||||
// get the total number of fingers touching the screen
|
||||
self.touchesCount = event.touches.length;
|
||||
// since we're looking for a swipe (single finger) and not a gesture (multiple fingers),
|
||||
// check that only one finger was used
|
||||
|
||||
if (self.touchesCount == 1) {
|
||||
// get the coordinates of the touch
|
||||
self.startTouchXPosition = event.touches[0].pageX;
|
||||
self.startTouchYPosition = event.touches[0].pageY;
|
||||
} else {
|
||||
// more than one finger touched so cancel
|
||||
self.touchCancel(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
touchMove: function (event) {
|
||||
var self = this;
|
||||
event.preventDefault();
|
||||
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
//var currentPointers = event.getPointerList();
|
||||
debug.info('touch move length: ' + self.touchesCount);
|
||||
if (self.touchesCount === 1) {
|
||||
debug.info('touchmove');
|
||||
self.currentXTouchPosition = event.pageX;
|
||||
self.currentYTouchPosition = event.pageY;
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
} else {
|
||||
if (event.touches.length == 1) {
|
||||
self.currentXTouchPosition = event.touches[0].pageX;
|
||||
self.currentYTouchPosition = event.touches[0].pageY;
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
touchEnd: function (event, callback) {
|
||||
var self = this;
|
||||
event.preventDefault();
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
debug.info('calculate swipe length');
|
||||
self.swipeLength = self.calculateSwipeAngle(self.startTouchXPosition, self.currentXTouchPosition, self.startTouchYPosition, self.currentYTouchPosition);
|
||||
debug.info('swipe length ' + self.swipeLength);
|
||||
// if the user swiped more than the minimum length, perform the appropriate action
|
||||
if (self.swipeLength >= self.options.minSwipeLength) {
|
||||
var swipeAngle = self.getSwipeAngle(self.startTouchXPosition, self.currentXTouchPosition, self.startTouchYPosition, self.currentYTouchPosition);
|
||||
var swipeDirection = self.determineSwipeDirection(swipeAngle);
|
||||
callback(swipeDirection); // callback with the swipe direction
|
||||
self.touchCancel(event); // reset the variables
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
} else {
|
||||
// check to see if more than one finger was used and that there is an ending coordinate
|
||||
if (self.touchesCount == 1 && self.currentXTouchPosition != 0) {
|
||||
debug.info('calculate swipe length');
|
||||
self.swipeLength = self.calculateSwipeAngle(self.startTouchXPosition, self.currentXTouchPosition, self.startTouchYPosition, self.currentYTouchPosition);
|
||||
debug.info('swipe length ' + self.swipeLength);
|
||||
// if the user swiped more than the minimum length, perform the appropriate action
|
||||
if (self.swipeLength >= self.options.minSwipeLength) {
|
||||
var swipeAngle = self.getSwipeAngle(self.startTouchXPosition, self.currentXTouchPosition, self.startTouchYPosition, self.currentYTouchPosition);
|
||||
var swipeDirection = self.determineSwipeDirection(swipeAngle);
|
||||
callback(swipeDirection); // callback with the swipe direction
|
||||
self.touchCancel(event); // reset the variables
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
} else {
|
||||
self.touchCancel(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
touchCancel: function (event) {
|
||||
var self = this;
|
||||
// reset the variables back to default values
|
||||
self.touchesCount = 0;
|
||||
self.startTouchXPosition = 0;
|
||||
self.startTouchYPosition = 0;
|
||||
self.currentXTouchPosition = 0;
|
||||
self.currentYTouchPosition = 0;
|
||||
self.swipeLength = 0;
|
||||
},
|
||||
|
||||
calculateSwipeAngle: function (startXPos, currentXPos, startYPos, currentYPos) {
|
||||
// determine the length of the swipe using distance formula
|
||||
return Math.round(Math.sqrt(Math.pow(currentXPos - startXPos, 2) + Math.pow(currentYPos - startYPos, 2)));
|
||||
},
|
||||
|
||||
getSwipeAngle: function (startXPos, currentXPos, startYPos, currentYPos) {
|
||||
var x = startXPos - currentXPos;
|
||||
var y = currentYPos - startYPos;
|
||||
var r = Math.atan2(y, x); //angle in radians (Cartesian system)
|
||||
var swipeAngle = Math.round(r * 180 / Math.PI); //angle in degrees
|
||||
if (swipeAngle < 0) { swipeAngle = 360 - Math.abs(swipeAngle); }
|
||||
return swipeAngle;
|
||||
},
|
||||
|
||||
determineSwipeDirection: function (swipeAngle) {
|
||||
if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
|
||||
return 'left';
|
||||
} else if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
|
||||
return 'left';
|
||||
} else if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
|
||||
return 'right';
|
||||
} else if ((swipeAngle > 45) && (swipeAngle < 135)) {
|
||||
return 'down';
|
||||
} else {
|
||||
return 'up';
|
||||
}
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
File diff suppressed because one or more lines are too long
@@ -1,35 +0,0 @@
|
||||
<div ng-controller="CharacterCtrl">
|
||||
|
||||
<figure class="herobox"
|
||||
data-name="{{username(user.auth)}}"
|
||||
data-level="{{user.stats.lvl}}"
|
||||
data-checkuser="isUser"
|
||||
>
|
||||
<div class='character-sprites'>
|
||||
<span class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}'></span>
|
||||
<span class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}'></span>
|
||||
<span class="{{equipped(user, 'armor')}}"></span>
|
||||
<span class="{{equipped(user, 'head')}}"></span>
|
||||
<span class="{{user.preferences.gender}}_head_0"></span>
|
||||
<span class='{{user.preferences.gender}}_shield_{{user.items.shield}}'></span>
|
||||
<span class='{{user.preferences.gender}}_weapon_{{user.items.weapon}}'></span>
|
||||
</div>
|
||||
</figure>
|
||||
|
||||
|
||||
<div class="user">
|
||||
{{user.auth.username}}<br>
|
||||
level {{user.stats.lvl}}
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="meter animate">
|
||||
<span style="width: {{hpPercent(user.stats.hp)}}%"><span></span></span>
|
||||
</div>
|
||||
|
||||
<div class="meter animate orange">
|
||||
<span style="width: {{expPercent(user.stats.exp, user.stats.lvl)}}%"><span></span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-controller="userAvatarCtrl"></div>
|
||||
@@ -1,61 +0,0 @@
|
||||
<div ng-controller="StatsCtrl"></div>
|
||||
|
||||
<div ng-controller="TaskDetailsCtrl">
|
||||
|
||||
<!-- Details Page -->
|
||||
<div ng-hide="editing">
|
||||
<a ng-click='goBack()'>Back</a> | <a ng-click="edit()">Edit</a>
|
||||
|
||||
<h2><span ng-show="task.completed">√ </span>{{task.text}}</h2>
|
||||
<p>{{task.notes}}</p>
|
||||
|
||||
|
||||
<!-- Habits -->
|
||||
<span ng-show="task.type == 'habit'" ng-cloak>
|
||||
<input type="button" value="+" ng-click="score(task,'up')"/>
|
||||
<input type="button" value="-" ng-click="score(task,'down')"/>
|
||||
</span>
|
||||
|
||||
{{task.title}}
|
||||
|
||||
<!-- Daily, Todo -->
|
||||
<input class="toggle" type="checkbox" ng-model="task.completed" ng-show="task.type == 'daily' || task.type == 'todo'" ng-cloak />
|
||||
|
||||
<input type="button" value="Buy ({{task.value}})" ng-show="task.type == 'reward'" ng-cloak />
|
||||
|
||||
<!-- Rewards -->
|
||||
<span></span>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Edit Page -->
|
||||
<div ng-show="editing">
|
||||
<a ng-click='cancel()'>Cancel</a> | <a ng-click='save()'>Save</a> | <a ng-click='delete()'>Delete</a>
|
||||
|
||||
Title: <input type='input' ng-model="task.text" /><br/>
|
||||
Notes: <textarea ng-model="task.notes" />
|
||||
|
||||
<!-- Habits -->
|
||||
<span ng-show="task.type == 'habit'" ng-cloak>
|
||||
<input type="checkbox" ng-model='task.up'> Up<br/>
|
||||
<input type="checkbox" ng-model='task.down'> Down
|
||||
</span>
|
||||
|
||||
<!-- Dailies -->
|
||||
<div ng-show="task.type == 'daily'">
|
||||
TODO: Repeat
|
||||
</div>
|
||||
|
||||
<!-- Todos -->
|
||||
<div ng-show="task.type == 'todo'">
|
||||
TODO: Due Date
|
||||
</div>
|
||||
|
||||
<!-- Rewards -->
|
||||
<div ng-hide="task.type == 'reward'">
|
||||
TODO: Difficulty
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,33 +0,0 @@
|
||||
<div ng-controller="LoginCtrl">
|
||||
|
||||
<div ng-controller="CharacterCtrl">
|
||||
|
||||
<div class="herobox">
|
||||
<div class='character-sprites'>
|
||||
<span class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}'></span>
|
||||
<span class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}'></span>
|
||||
<span class="{{equipped(user, 'armor')}}"></span>
|
||||
<span class="{{equipped(user, 'head')}}"></span>
|
||||
<span class="{{user.preferences.gender}}_head_0"></span>
|
||||
<span class='{{user.preferences.gender}}_shield_{{user.items.shield}}'></span>
|
||||
<span class='{{user.preferences.gender}}_weapon_{{user.items.weapon}}'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="user">
|
||||
{{user.auth.local.username}}<br>
|
||||
level {{user.stats.lvl}}
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="meter animate">
|
||||
<span style="width: {{hpPercent(user.stats.hp)}}%"><span></span></span>
|
||||
</div>
|
||||
|
||||
<div class="meter animate orange">
|
||||
<span style="width: {{expPercent(user.stats.exp, user.stats.lvl)}}%"><span></span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,11 +0,0 @@
|
||||
<div class='login-page' ng-controller='AuthCtrl'>
|
||||
<div style="width:200px; margin:0 auto">
|
||||
<form ng-submit="apiLogin()" id="apiLoginForm">
|
||||
<label for="uuid">UUID</label><input type='text' id="uuid1" ng-model="uuid" required/>
|
||||
<label for="apiToken">API Token</label><input type='text' id="apiToken1" ng-model="apiToken" required/><br />
|
||||
<input type='submit' value="Submit" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,72 +0,0 @@
|
||||
<div style="margin:10px">
|
||||
<ul class="nav nav-tabs game-tabs">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" data-target="#profile-customize"><i class="icon-user"></i> Profile</a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="party-tab-link" data-toggle="tab" data-target="#profile-groups"><i class="icon-heart"></i> Groups</a>
|
||||
</li>
|
||||
<!--$1bv-->
|
||||
<li>
|
||||
<a data-toggle="tab" data-target="#profile-inventory"><i class="icon-gift"></i> Inventory</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" data-target="#profile-stable"><i class="icon-leaf"></i> Stable</a>
|
||||
</li>
|
||||
<!--$$1bv-->
|
||||
<li>
|
||||
<a data-toggle="tab" data-target="#profile-tavern"><i class="icon-eye-close"></i> Tavern</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" data-target="#profile-achievements"><i class="icon-certificate"></i> Achievements</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" data-target="#profile-settings"><i class="icon-wrench"></i> Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tab-content" style="margin:10px">
|
||||
<div class="row-fluid">
|
||||
<div class="span4 border-right">
|
||||
<div ng-controller="userAvatarCtrl" class="userAvatar">
|
||||
<div>
|
||||
<menu type="list">
|
||||
<li class="customize-menu">
|
||||
<menu label="Head">
|
||||
<button type="button" class="m_head_0 customize-option" data-value="m" ng-click="changeSex('m')"></button>
|
||||
<button type="button" class="f_head_0 customize-option" data-value="f" ng-click="changeSex('f')"></button>
|
||||
</menu>
|
||||
</li>
|
||||
|
||||
<li class="customize-menu">
|
||||
<menu label="Hair">
|
||||
<button type="button" class="{{user.preferences.gender}}_hair_blond customize-option" data-value="blond" ng-click="changeHair('blond')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_hair_black customize-option" data-value="black" ng-click="changeHair('black')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_hair_brown customize-option" data-value="brown" ng-click="changeHair('brown')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_hair_white customize-option" data-value="white" ng-click="changeHair('white')"></button>
|
||||
</menu>
|
||||
</li>
|
||||
|
||||
<li class="customize-menu">
|
||||
<menu label="Skin">
|
||||
<button type="button" class="{{user.preferences.gender}}_skin_dead customize-option" data-value="dead" ng-click="changeSkin('dead')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_skin_orc customize-option" data-value="orc" ng-click="changeSkin('orc')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_skin_asian customize-option" data-value="asian" ng-click="changeSkin('asian')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_skin_black customize-option" data-value="black" ng-click="changeSkin('black')"></button>
|
||||
<button type="button" class="{{user.preferences.gender}}_skin_white customize-option" data-value="white" ng-click="changeSkin('white')"></button>
|
||||
</menu>
|
||||
</li>
|
||||
|
||||
<li class="customize-menu">
|
||||
<menu label="Clothing" ng-show="user.preferences.gender == 'f'">
|
||||
<button type="button" class="f_armor_0_v1 customize-option" data-value="v1" ng-click="changeArmor('v1')"></button>
|
||||
<button type="button" class="f_armor_0_v2 customize-option" data-value="v2" ng-click="changeArmor('v2')"></button>
|
||||
</menu>
|
||||
</li>
|
||||
</menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,31 +0,0 @@
|
||||
<div ng-controller="CharacterCtrl">
|
||||
|
||||
<div class="herobox">
|
||||
<div class='character-sprites' ng-click="showUserAvatar()">
|
||||
<span class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}'></span>
|
||||
<span class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}'></span>
|
||||
<span class="{{equipped(user, 'armor')}}"></span>
|
||||
<span class="{{equipped(user, 'head')}}"></span>
|
||||
<span class="{{user.preferences.gender}}_head_0"></span>
|
||||
<span class='{{user.preferences.gender}}_shield_{{user.items.shield}}'></span>
|
||||
<span class='{{user.preferences.gender}}_weapon_{{user.items.weapon}}'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="user">
|
||||
{{user.auth.local.username}}<br>
|
||||
level {{user.stats.lvl}}<br>
|
||||
Gold: {{user.stats.gp | gold}}
|
||||
Silver: {{user.stats.gp | silver}}
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="meter animate">
|
||||
<span style="width: {{hpPercent(user.stats.hp)}}%"><span></span></span>
|
||||
</div>
|
||||
|
||||
<div class="meter animate orange">
|
||||
<span style="width: {{expPercent(user.stats.exp, user.stats.lvl)}}%"><span></span></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +0,0 @@
|
||||
<div ng-controller="SettingsCtrl">
|
||||
<div>Id:<input type="text" ng-model="settings.auth.apiId">
|
||||
Token:<input type="text" ng-model="settings.auth.apiToken">
|
||||
<input type="button" value="Save" ng-click="auth(settings.auth.apiId,settings.auth.apiToken)">
|
||||
<input type="button" value="RESET APPLICATION" ng-click="resetApp()">
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "yeoman",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"angular": "~1.0.5",
|
||||
"jquery": "~1.9.1",
|
||||
"json3": "~3.2.4",
|
||||
"es5-shim": "~2.0.5",
|
||||
"angular-resource": "~1.0.5",
|
||||
"angular-cookies": "~1.0.5",
|
||||
"angular-sanitize": "~1.0.5",
|
||||
"underscore": "*",
|
||||
"moment": "*",
|
||||
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git",
|
||||
"hammerjs": "~1.0.5",
|
||||
"angular-hammer": "~1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "~1.0.5",
|
||||
"angular-scenario": "~1.0.5"
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"name": "yeoman",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"express": "~3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "0.4.0rc7",
|
||||
"grunt-contrib-copy": "0.4.0rc7",
|
||||
"grunt-contrib-concat": "0.1.2rc6",
|
||||
"grunt-contrib-coffee": "0.4.0rc7",
|
||||
"grunt-contrib-uglify": "0.1.1rc6",
|
||||
"grunt-contrib-compass": "0.1.1rc8",
|
||||
"grunt-contrib-jshint": "0.1.1rc6",
|
||||
"grunt-contrib-mincss": "0.4.0rc7",
|
||||
"grunt-contrib-connect": "0.1.1rc6",
|
||||
"grunt-contrib-clean": "0.4.0rc6",
|
||||
"grunt-contrib-htmlmin": "0.1.1rc7",
|
||||
"grunt-contrib-imagemin": "0.1.1rc8",
|
||||
"grunt-contrib-livereload": "0.1.0rc8",
|
||||
"grunt-bower-hooks": "~0.2.0",
|
||||
"grunt-usemin": "~0.1.7",
|
||||
"grunt-regarde": "~0.1.1",
|
||||
"gruntacular": "~0.1.1",
|
||||
"grunt-open": "~0.1.0",
|
||||
"matchdep": "~0.1.1",
|
||||
"grunt-google-cdn": "~0.1.0",
|
||||
"grunt-ngmin": "~0.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
habitrpg.controller('TasksCtrl', function TasksCtrl($scope, $rootScope, $location, filterFilter, User, Algos, Helpers, Notification) {
|
||||
|
||||
$scope.user = User.user;
|
||||
|
||||
|
||||
$scope.score = function (task, direction) {
|
||||
//save current stats to compute the difference after scoring.
|
||||
var statsDiff = {};
|
||||
var oldStats = _.clone(User.user.stats);
|
||||
|
||||
Algos.score(User.user, task, direction);
|
||||
|
||||
//compute the stats change.
|
||||
_.each(oldStats, function (value, key) {
|
||||
var newValue = User.user.stats[key];
|
||||
if (newValue !== value) {
|
||||
statsDiff[key] = newValue - value;
|
||||
}
|
||||
});
|
||||
//notify user if there are changes in stats.
|
||||
if (Object.keys(statsDiff).length > 0) {
|
||||
// Notification.push({type: 'stats', stats: statsDiff});
|
||||
}
|
||||
User.log({op: 'score', task: task, dir: direction});
|
||||
};
|
||||
|
||||
$scope.save = function(task) {
|
||||
|
||||
var ops = ([
|
||||
{op: 'set', path: "tasks." + task.id + ".text", value: task.text},
|
||||
{op: 'set', path: "tasks." + task.id + ".notes", value: task.notes},
|
||||
{op: 'set', path: "tasks." + task.id + ".up", value: task.up},
|
||||
{op: 'set', path: "tasks." + task.id + ".down", value: task.down},
|
||||
{op: 'set', path: "tasks." + task.id + ".priority", value: task.priority},
|
||||
{op: 'set', path: "tasks." + task.id + ".date", value: task.date},
|
||||
{op: 'set', path: "tasks." + task.id + ".price", value: task.price},
|
||||
])
|
||||
|
||||
_.each(task.tags, function(el, key, list) {
|
||||
ops.push({op: 'set', path: "tasks." + task.id + ".tags." + key, value: el})
|
||||
})
|
||||
|
||||
_.each(task.repeat, function(el, key, list) {
|
||||
ops.push({op: 'set', path: "tasks." + task.id + ".repeat." + key, value: el})
|
||||
})
|
||||
|
||||
User.log(ops)
|
||||
|
||||
task.editing = false
|
||||
|
||||
}
|
||||
|
||||
|
||||
$scope.getRepeat = function(task, repeat) {
|
||||
var enabled = '';
|
||||
_.each(task.repeat, function(el, key, list) {
|
||||
if (key == repeat && el == true) {
|
||||
enabled = true
|
||||
}
|
||||
})
|
||||
|
||||
if (enabled) {
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
$scope.setRepeat = function(task, repeat) {
|
||||
|
||||
if (typeof task.repeat == 'undefined') {
|
||||
var obj = {}
|
||||
obj[repeat] = true;
|
||||
|
||||
task.repeat = {}
|
||||
task.repeat = obj
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
if (!task.repeat[repeat]) {
|
||||
task.repeat[repeat] = true
|
||||
}else{
|
||||
task.repeat[repeat] = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.addTag = function(task, tag) {
|
||||
var obj = {}
|
||||
obj[tag] = true
|
||||
task.tags.push(obj)
|
||||
}
|
||||
|
||||
$scope.toggleTag = function(task, tag) {
|
||||
var obj = {}
|
||||
if (typeof task.tags != 'undefined') {
|
||||
if (!task.tags[tag]) {
|
||||
task.tags[tag] = false;
|
||||
}else{
|
||||
task.tags[tag] = true
|
||||
}
|
||||
}else{
|
||||
task.tags = {}
|
||||
task.tags[tag] = true
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -55,19 +55,18 @@ habitrpg.directive('whenScrolled', function() {
|
||||
* Add sortable
|
||||
*/
|
||||
habitrpg.directive('sort', function (User) {
|
||||
return ['$scope', '$rootScope', 'element', 'attrs', 'ngModel',
|
||||
function($scope, $rootScope, element, attrs, ngModel) {
|
||||
$(element).sortable({
|
||||
axis: "y",
|
||||
start: function (event, ui) {
|
||||
ui.item.data('startIndex', ui.item.index());
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
var taskType = $rootScope.taskContext.type;
|
||||
var startIndex = ui.item.data('startIndex');
|
||||
var task = User.user[taskType][startIndex];
|
||||
User.log({op: 'sortTask', data: task, from: startIndex, to: ui.item.index()});
|
||||
}
|
||||
});
|
||||
return ['$scope', 'element', 'attrs', 'ngModel', function($scope, element, attrs, ngModel) {
|
||||
$(element).sortable({
|
||||
axis: "y",
|
||||
start: function (event, ui) {
|
||||
ui.item.data('startIndex', ui.item.index());
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
var taskType = angular.element(ui.item[0]).scope().task.type + 's'
|
||||
var startIndex = ui.item.data('startIndex');
|
||||
var task = User.user[taskType][startIndex];
|
||||
User.log({op: 'sortTask', data: task, from: startIndex, to: ui.item.index()});
|
||||
}
|
||||
});
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
+6
-1
@@ -6,6 +6,11 @@ html
|
||||
script(type='text/javascript').
|
||||
window.env = !{JSON.stringify(env)};
|
||||
|
||||
style.
|
||||
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// CSS
|
||||
link(rel='stylesheet', href='/bower_components/bootstrap/docs/assets/css/bootstrap.css')
|
||||
link(rel='stylesheet', href='/bower_components/bootstrap/docs/assets/css/bootstrap-responsive.css')
|
||||
@@ -56,7 +61,7 @@ html
|
||||
meta(name='viewport', content='width=device-width')
|
||||
meta(name='apple-mobile-web-app-capable', content='yes')
|
||||
|
||||
body(ng-app="habitrpg", ng-controller="RootCtrl")
|
||||
body(ng-app="habitrpg", ng-controller="RootCtrl", ng-cloak)
|
||||
include ./shared/modals/index
|
||||
include ./shared/header/header
|
||||
|
||||
|
||||
Reference in New Issue
Block a user