mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-08-03 08:21:07 +00:00
rewrite: merge in some more litenull stuff & delete the superfluous files
This commit is contained in:
parent
aafb9b6cdd
commit
1b22928c0a
49 changed files with 131 additions and 44284 deletions
|
|
@ -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
377
archive/litenull_rewrite/app/scripts/vendor/index.js
vendored
377
archive/litenull_rewrite/app/scripts/vendor/index.js
vendored
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
111
archive/litenull_rewrite/scripts/controllers/tasksCtrl.js
Normal file
111
archive/litenull_rewrite/scripts/controllers/tasksCtrl.js
Normal file
|
|
@ -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,15 +55,14 @@ habitrpg.directive('whenScrolled', function() {
|
|||
* Add sortable
|
||||
*/
|
||||
habitrpg.directive('sort', function (User) {
|
||||
return ['$scope', '$rootScope', 'element', 'attrs', 'ngModel',
|
||||
function($scope, $rootScope, element, attrs, ngModel) {
|
||||
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 = $rootScope.taskContext.type;
|
||||
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,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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue