rewrite: merge in some more litenull stuff & delete the superfluous files

This commit is contained in:
Tyler Renelle
2013-08-28 13:38:04 -04:00
parent aafb9b6cdd
commit 1b22928c0a
49 changed files with 131 additions and 44284 deletions
-3
View File
@@ -1,3 +0,0 @@
{
"directory": "app/bower_components"
}
-22
View File
@@ -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.
-132
View File
@@ -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
-377
View File
@@ -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>
-22
View File
@@ -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"
}
}
-33
View File
@@ -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
}
}
});
+14 -15
View File
@@ -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
View File
@@ -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