Commit fe2c7edc6f5b065176746b7f3029bf103ff2e64f

Authored by Andrew Buss
1 parent 97093984be

fix flashcard scaling; still need to fix font size scaling

Showing 6 changed files with 127 additions and 140 deletions Inline Diff

angular.module('flashy', [ 1 1 angular.module('flashy', [
'flashy.LogoutController', 2 2 'flashy.LogoutController',
'flashy.LoginController', 3 3 'flashy.LoginController',
'flashy.RootController', 4 4 'flashy.RootController',
'flashy.FeedController', 5 5 'flashy.FeedController',
'flashy.DeckController', 6 6 'flashy.DeckController',
'flashy.ClassAddController', 7 7 'flashy.ClassAddController',
'flashy.RequestResetController', 8 8 'flashy.RequestResetController',
'flashy.StudyController', 9 9 'flashy.StudyController',
'flashy.UserService', 10 10 'flashy.UserService',
'flashy.FlashcardDirective', 11 11 'flashy.FlashcardDirective',
'flashy.ResetPasswordController', 12 12 'flashy.ResetPasswordController',
'flashy.VerifyEmailController', 13 13 'flashy.VerifyEmailController',
'flashy.CardListController', 14 14 'flashy.CardListController',
'ngCookies']). 15 15 'ngCookies']).
config(function ($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) { 16 16 config(function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) {
'use strict'; 17 17 'use strict';
$httpProvider.defaults.withCredentials = true; 18 18 $httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; 19 19 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 20 20 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
21 21
var arrayMethods = Object.getOwnPropertyNames(Array.prototype); 22 22 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
arrayMethods.forEach(attachArrayMethodsToNodeList); 23 23 arrayMethods.forEach(attachArrayMethodsToNodeList);
function attachArrayMethodsToNodeList(methodName) { 24 24 function attachArrayMethodsToNodeList(methodName) {
if (methodName !== 'length') { 25 25 if (methodName !== 'length') {
NodeList.prototype[methodName] = Array.prototype[methodName]; 26 26 NodeList.prototype[methodName] = Array.prototype[methodName];
} 27 27 }
}; 28 28 };
29 29
$httpProvider.interceptors.push(function ($q) { 30 30 $httpProvider.interceptors.push(function($q) {
return { 31 31 return {
'responseError': function (rejection) { 32 32 'responseError': function(rejection) {
if (rejection.status >= 500) { 33 33 if (rejection.status >= 500) {
console.log('got error'); 34 34 console.log('got error');
console.log(rejection); 35 35 console.log(rejection);
$('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>'); 36 36 $('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>');
} 37 37 }
return $q.reject(rejection); 38 38 return $q.reject(rejection);
} 39 39 }
}; 40 40 };
}); 41 41 });
$locationProvider.html5Mode(true); 42 42 $locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/404'); 43 43 $urlRouterProvider.otherwise('/404');
var auth_resolve = { 44 44 var auth_resolve = {
authorize: function ($q, $state, UserService) { 45 45 authorize: function($q, $state, UserService) {
console.log('resolving user before continuing'); 46 46 console.log('resolving user before continuing');
var redirectAsNeeded = function () { 47 47 var redirectAsNeeded = function() {
if (!UserService.isLoggedIn()) { 48 48 if (!UserService.isLoggedIn()) {
console.log(UserService.getUserData()); 49 49 console.log(UserService.getUserData());
console.log('making the user log in'); 50 50 console.log('making the user log in');
$state.go('login'); 51 51 $state.go('login');
} 52 52 }
}; 53 53 };
if (UserService.isResolved()) return redirectAsNeeded(); 54 54 if (UserService.isResolved()) return redirectAsNeeded();
return UserService.getUserData().then(redirectAsNeeded); 55 55 return UserService.getUserData().then(redirectAsNeeded);
} 56 56 }
}; 57 57 };
$stateProvider. 58 58 $stateProvider.
state('login', { 59 59 state('login', {
url: '/login', 60 60 url: '/login',
templateUrl: 'templates/login.html', 61 61 templateUrl: 'templates/login.html',
controller: 'LoginController' 62 62 controller: 'LoginController'
}). 63 63 }).
state('logout', { 64 64 state('logout', {
resolve: auth_resolve, 65 65 resolve: auth_resolve,
url: '/logout', 66 66 url: '/logout',
templateUrl: 'templates/logout.html', 67 67 templateUrl: 'templates/logout.html',
controller: 'LogoutController' 68 68 controller: 'LogoutController'
}). 69 69 }).
state('root', { 70 70 state('root', {
resolve: auth_resolve, 71 71 resolve: auth_resolve,
url: '/', 72 72 url: '/',
controller: 'RootController' 73 73 controller: 'RootController'
}). 74 74 }).
state('feed', { 75 75 state('feed', {
resolve: auth_resolve, 76 76 resolve: auth_resolve,
url: '/feed/{sectionId}', 77 77 url: '/feed/{sectionId}',
templateUrl: 'templates/feed.html', 78 78 templateUrl: 'templates/feed.html',
controller: 'FeedController' 79 79 controller: 'FeedController'
}). 80 80 }).
state('cardlist', { 81 81 state('cardlist', {
resolve: auth_resolve, 82 82 resolve: auth_resolve,
url: '/cards/{sectionId}', 83 83 url: '/cards/{sectionId}',
templateUrl: 'templates/cardlist.html', 84 84 templateUrl: 'templates/cardlist.html',
controller: 'CardListController' 85 85 controller: 'CardListController'
}). 86 86 }).
state('addclass', { 87 87 state('addclass', {
resolve: auth_resolve, 88 88 resolve: auth_resolve,
url: '/addclass', 89 89 url: '/addclass',
templateUrl: 'templates/addclass.html', 90 90 templateUrl: 'templates/addclass.html',
controller: 'ClassAddController' 91 91 controller: 'ClassAddController'
}). 92 92 }).
state('deck', { 93 93 state('deck', {
resolve: auth_resolve, 94 94 resolve: auth_resolve,
url: '/deck/{sectionId}', 95 95 url: '/deck/{sectionId}',
templateUrl: 'templates/deck.html', 96 96 templateUrl: 'templates/deck.html',
controller: 'DeckController' 97 97 controller: 'DeckController'
}). 98 98 }).
state('study', { 99 99 state('study', {
resolve: auth_resolve, 100 100 resolve: auth_resolve,
url: '/study', 101 101 url: '/study',
templateUrl: 'templates/study.html', 102 102 templateUrl: 'templates/study.html',
controller: 'StudyController' 103 103 controller: 'StudyController'
}). 104 104 }).
state('flashcard', { 105 105 state('flashcard', {
resolve: auth_resolve, 106 106 resolve: auth_resolve,
url: '/flashcard', 107 107 url: '/flashcard',
templateUrl: 'templates/flashcard.html', 108 108 templateUrl: 'templates/flashcard.html',
controller: 'FlashcardController' 109 109 controller: 'FlashcardController'
}). 110 110 }).
state('requestpasswordreset', { 111 111 state('requestpasswordreset', {
url: '/requestpasswordreset', 112 112 url: '/requestpasswordreset',
templateUrl: 'templates/requestpasswordreset.html', 113 113 templateUrl: 'templates/requestpasswordreset.html',
controller: 'RequestResetController' 114 114 controller: 'RequestResetController'
}). 115 115 }).
state('resetpassword', { 116 116 state('resetpassword', {
url: '/resetpassword/{uid}/{token}', 117 117 url: '/resetpassword/{uid}/{token}',
templateUrl: 'templates/resetpassword.html', 118 118 templateUrl: 'templates/resetpassword.html',
controller: 'ResetPasswordController' 119 119 controller: 'ResetPasswordController'
}). 120 120 }).
state('verifyemail', { 121 121 state('verifyemail', {
resolve: auth_resolve, 122 122 resolve: auth_resolve,
url: '/verifyemail/{key}', 123 123 url: '/verifyemail/{key}',
templateUrl: 'templates/verifyemail.html', 124 124 templateUrl: 'templates/verifyemail.html',
controller: 'VerifyEmailController' 125 125 controller: 'VerifyEmailController'
}). 126 126 }).
state('404', { 127 127 state('404', {
url: '/404', 128 128 url: '/404',
template: "<h1>This page doesn't exist!</h1>" 129 129 template: "<h1>This page doesn't exist!</h1>"
}); 130 130 });
}). 131 131 }).
run(function ($rootScope, $state, $stateParams, $location, UserService) { 132 132 run(function($rootScope, $state, $stateParams, $location, UserService) {
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) { 133 133 $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
console.log('failed to change state: ' + error); 134 134 console.log('failed to change state: ' + error);
$state.go('login'); 135 135 $state.go('login');
}); 136 136 });
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { 137 137 $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) { 138 138 if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) {
localStorage.setItem('last_state', toState.name); 139 139 localStorage.setItem('last_state', toState.name);
localStorage.setItem('last_state_params', JSON.stringify(toParams)); 140 140 localStorage.setItem('last_state_params', JSON.stringify(toParams));
} 141 141 }
}); 142 142 });
}); 143 143 });
144 144
scripts/FeedController.js View file @ fe2c7ed
angular.module('flashy.FeedController', ['ui.router']). 1 1 angular.module('flashy.FeedController', ['ui.router']).
2 2
controller('FeedController', function ($scope, $rootScope, $stateParams, $state, $http, $window, UserService) { 3 3 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, UserService) {
console.log('Hello from feed'); 4 4 console.log('Hello from feed');
sectionId = $stateParams.sectionId; 5 5 sectionId = $stateParams.sectionId;
$rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId}); 6 6 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
$scope.cards = false; 7 7 $scope.cards = false;
$scope.data = [0]; // raw data 8 8 $scope.data = []; // raw data
$scope.cardCols = []; // organized data 9 9 $scope.cardCols = []; // organized data
$scope.cardRows = []; // visual data 10 10 $scope.numCols = 0;
$scope.cols = 0; 11 11
12 12 function calculate_cols() {
/*var nullCard = { 13 13 var avail = $window.innerWidth - 17;
id: -1, 14 14 return Math.max(1, Math.floor(avail / 250));
};*/ 15 15 }
/* Handles number of columns */ 16 16
function calculate_cols() { 17 17 function refreshColumnWidth() {
var avail = $window.innerWidth - 17; 18 18 avail = $window.innerWidth - 17;
return Math.floor(avail / 250); 19 19 width = Math.floor(avail / Math.floor(avail / 250));
} 20 20 $('.cardColumn').css({
21 21 width: width + 'px',
$scope.rowSpace = function(columns) { //transpose? as name 22 22 //height: (width * 3 / 5) + 'px',
var rows = []; 23 23
var maxColLen = 0; 24 24 });
for (i = 0; i < columns.length; i++) 25 25 $('.cardColumn .card.flashy').css({
if (maxColLen < columns[i].length) 26 26 width: width + 'px',
maxColLen = columns[i].length; 27 27 height: (width * 3 / 5) + 'px'
console.log('max col len:' + maxColLen); 28 28 });
for (i = 0; i < maxColLen; i++) 29 29 $('.cardColumn .card.flashy .card-content').css({
rows.push([]); 30 30 'font-size': 100 * width / 250 + '%'
for (i = 0; i < rows.length; i++) { 31 31 });
for (j = 0; j < columns.length; j++) { 32 32 }
if (i >= columns[j].length) 33 33
continue; // for now, no placeholder 34
console.log(columns[j][i]); 35
rows[i].push(columns[j][i]); 36
} 37
} 38
return rows; 39
} 40
41
$scope.refreshLayout = function() { 42 34 $scope.refreshLayout = function() {
console.log('refreshing layout'); 43 35 refreshColumnWidth();
//if (calculate_cols() == $scope.cols) return; 44 36 if (calculate_cols() == $scope.numCols) return;
$scope.cols = calculate_cols(); 45 37 $scope.numCols = calculate_cols();
38 console.log('refreshing layout for ' + $scope.numCols + ' columns');
39
$scope.cardCols = []; 46 40 $scope.cardCols = [];
for (i = 0; i < $scope.cols; i++) { 47 41 for (i = 0; i < $scope.numCols; i++) {
$scope.cardCols.push([]); // empty columns 48 42 $scope.cardCols.push([]); // empty columns
} 49 43 }
var count = 0; 50 44 var count = 0;
//console.log($scope.data); 51
for (i = 0; i < $scope.data.length; i++) { 52 45 for (i = 0; i < $scope.data.length; i++) {
if (count >= $scope.cols) count = 0; 53 46 if (count >= $scope.numCols) count = 0;
$scope.cardCols[count].push($scope.data[i]); // fill empty columns 54 47 $scope.cardCols[count].push($scope.data[i]); // fill empty columns
count++; 55 48 count++;
} 56 49 }
$scope.cardRows = $scope.rowSpace($scope.cardCols); 57 50 };
console.log($scope.cardRows); 58
} 59
60
angular.element($window).bind('resize', $scope.refreshLayout()); 61
console.log('cols:' + calculate_cols()); 62
63 51
$scope.refreshCards = function () { 64 52 angular.element($window).bind('resize', $scope.refreshLayout);
53
54 $scope.refreshCards = function() {
$http.get('/api/sections/' + sectionId + '/feed/'). 65 55 $http.get('/api/sections/' + sectionId + '/feed/').
success(function (data) { 66 56 success(function(data) {
console.log(data); 67 57 console.log(data);
$scope.data = data; 68 58 $scope.data = data;
$scope.refreshLayout(); 69 59 $scope.refreshLayout();
console.log('success in refresh cards...'); 70 60 console.log('success in refresh cards...');
}). 71 61 }).
error(function (err) { 72 62 error(function(err) {
console.log('refresh fail'); 73 63 console.log('refresh fail');
}); 74 64 });
}; 75 65 };
76 66
$scope.add = function(card) { 77 67 $scope.add = function(card) {
console.log('adding card'); 78 68 console.log('adding card');
for (i = 0; i < $scope.cardCols.length ; i++) { 79 69 for (i = 0; i < $scope.cardCols.length; i++) {
if ($scope.cardCols.length == 0) { 80 70 if ($scope.cardCols.length == 0) {
$scope.cardCols.unshift(card); 81 71 $scope.cardCols.unshift(card);
$scope.cardRows = $scope.rowSpace($scope.cardCols) 82 72 return;
return; 83 73 }
} 84 74 }
} 85 75 var colNum = Math.floor(Math.random() * $scope.numCols);
var colNum = Math.floor(Math.random() * $scope.cols); 86 76 $scope.cardCols[colNum].unshift(card);
$scope.cardCols[colNum].unshift(card); 87 77 };
$scope.cardRows = $scope.rowSpace($scope.cardCols) 88 78
}; 89 79 $scope.hide = function(card) {
90 80 console.log('hiding card');
$scope.hide = function(card) { 91 81 console.log(card);
console.log('hiding card'); 92 82 var found = -1;
var found = -1; 93 83 for (i = 0; i < $scope.cardCols.length; i++) {
for (i = 0; i < $scope.cardCols.length ; i++) { 94 84 found = $scope.cardCols[i].indexOf(card);
found = $scope.cardCols[i].indexOf(card); 95 85 if (found != -1) {
if (found != -1) { 96 86 $scope.cardCols[i].splice(found, 1);
$scope.cardCols[i].splice(found, 1); 97 87 return;
$scope.cardRows = $scope.rowSpace($scope.cardCols) 98 88 }
return; 99 89 }
} 100 90 console.log('Error finding card to hide:');
} 101 91 console.log(card);
console.log('Error finding card to hide:') 102 92 };
console.log(card); 103 93
}; 104 94 /* Instance creation */
105 95 $http.get('/api/sections/' + sectionId + '/feed/').
/* Instance creation */ 106
$http.get('/api/sections/' + sectionId + '/feed/'). 107
success(function(data) { 108 96 success(function(data) {
console.log(data); 109 97 console.log(data);
if (data.length == 0) 110 98 if (data.length == 0)
$scope.cards = false; 111 99 $scope.cards = false;
$scope.data = data; 112 100 $scope.data = data;
$scope.refreshLayout(); 113 101 $scope.refreshLayout();
console.log('success in refresh cards...'); 114 102 console.log('success in refresh cards...');
}). 115 103 }).
error(function(err) { 116 104 error(function(err) {
console.log('pulling feed failed'); 117 105 console.log('pulling feed failed');
}); 118 106 });
119 107
var loc = window.location, new_uri; 120 108 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 121 109 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 122 110 new_uri = 'wss:';
} else { 123 111 } else {
new_uri = 'ws:'; 124 112 new_uri = 'ws:';
} 125 113 }
new_uri += '//' + loc.host; 126 114 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast'); 127 115 var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast');
128 116
ws.onopen = function () { 129 117 ws.onopen = function() {
console.log('websocket connected'); 130 118 console.log('websocket connected');
}; 131 119 };
ws.onmessage = function (e) { 132 120 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 133 121 console.log('got websocket message ' + e.data);
data = JSON.parse(e.data); 134 122 data = JSON.parse(e.data);
if (data.event_type == 'new_card') { 135 123 if (data.event_type == 'new_card') {
$scope.add(data.flashcard); 136 124 $scope.add(data.flashcard);
} 137 125 }
}; 138 126 };
ws.onerror = function (e) { 139 127 ws.onerror = function(e) {
console.error(e); 140 128 console.error(e);
}; 141 129 };
ws.onclose = function (e) { 142 130 ws.onclose = function(e) {
console.log('connection closed'); 143 131 console.log('connection closed');
}; 144 132 };
145 133
$scope.pushCard = function () { 146 134 $scope.pushCard = function() {
var i = 0; 147 135 var i = 0;
var blanks = []; 148 136 var blanks = [];
$('#new-card-input')[0].childNodes.forEach(function (node) { 149 137 $('#new-card-input')[0].childNodes.forEach(function(node) {
node = $(node)[0]; 150 138 node = $(node)[0];
console.log(node); 151 139 console.log(node);
if (node.tagName == 'B') { 152 140 if (node.tagName == 'B') {
text = $(node).text(); 153 141 text = $(node).text();
blanks.push([i, i + text.length]); 154 142 blanks.push([i, i + text.length]);
i += text.length; 155 143 i += text.length;
} else { 156 144 } else {
i += node.data.length; 157 145 i += node.data.length;
} 158 146 }
}); 159 147 });
text = $('#new-card-input').text(); 160 148 text = $('#new-card-input').text();
var myCard = { 161 149 var myCard = {
'text': text, 162 150 'text': text,
'mask': blanks, 163 151 'mask': blanks,
section: sectionId 164 152 section: sectionId
}; 165 153 };
$http.post('/api/flashcards/', myCard). 166 154 $http.post('/api/flashcards/', myCard).
success(function (data) { 167 155 success(function(data) {
console.log('flashcard push succeeded'); 168 156 console.log('flashcard push succeeded');
if (!UserService.hasVerifiedEmail()) { 169 157 if (!UserService.hasVerifiedEmail()) {
Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000); 170 158 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
} 171 159 }
}). 172 160 }).
error(function (error) { 173 161 error(function(error) {
console.log('something went wrong pushing a card!'); 174 162 console.log('something went wrong pushing a card!');
}); 175 163 });
listenForC = true; 176 164 listenForC = true;
$('#new-card-input').html(''); 177 165 $('#new-card-input').html('');
}; 178 166 };
179 167
/* Key bindings for the whole feed window. Hotkey it up! */ 180 168 /* Key bindings for the whole feed window. Hotkey it up! */
var listenForC = true; 181 169 var listenForC = true;
182 170
// Need to pass these options into openmodal and leanmodal, 183 171 // Need to pass these options into openmodal and leanmodal,
// otherwise the ready handler doesn't get called 184 172 // otherwise the ready handler doesn't get called
185 173
modal_options = { 186 174 modal_options = {
dismissible: true, // Modal can be dismissed by clicking outside of the modal 187 175 dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: 0, // Opacity of modal background 188 176 opacity: 0, // Opacity of modal background
in_duration: 300, // Transition in duration 189 177 in_duration: 300, // Transition in duration
out_duration: 200, // Transition out duration 190 178 out_duration: 200, // Transition out duration
ready: function () { 191 179 ready: function() {
listenForC = false; 192 180 listenForC = false;
console.log('modal OPENING'); 193 181 console.log('modal OPENING');
$('#new-card-input').focus(); 194 182 $('#new-card-input').focus();
}, 195 183 },
complete: function () { 196 184 complete: function() {
listenForC = true; 197 185 listenForC = true;
console.log('modal done, closing'); 198 186 console.log('modal done, closing');
$('#new-card-input').blur(); 199 187 $('#new-card-input').blur();
} 200 188 }
}; 201 189 };
202 190
$(document).keydown(function (e) { 203 191 $(document).keydown(function(e) {
console.log(e.which); 204 192 console.log(e.which);
var keyed = e.which; 205 193 var keyed = e.which;
if (keyed == 67 && listenForC) { // "c" or "C" for compose 206 194 if (keyed == 67 && listenForC) { // "c" or "C" for compose
$('#newCard').openModal(modal_options); 207 195 $('#newCard').openModal(modal_options);
e.preventDefault(); 208 196 e.preventDefault();
listenForC = false; 209 197 listenForC = false;
return false; 210 198 return false;
} else if (keyed == 27) { // enter or esc, respectively 211 199 } else if (keyed == 27) { // enter or esc, respectively
listenForC = true; 212 200 listenForC = true;
document.getElementById('new-card-input').value = ''; 213 201 document.getElementById('new-card-input').value = '';
} 214 202 }
}); 215 203 });
$scope.flashcard = ''; 216 204 $scope.flashcard = '';
$scope.text = ''; 217 205 $scope.text = '';
var selected_start = 0; 218 206 var selected_start = 0;
var selected_end = 0; 219 207 var selected_end = 0;
$(document).ready(function () { 220 208 $(document).ready(function() {
$('.tooltipped').tooltip({delay: 50}); 221 209 $('.tooltipped').tooltip({delay: 50});
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered 222 210 // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
$('.modal-trigger').leanModal(modal_options); 223 211 $('.modal-trigger').leanModal(modal_options);
$('#new-card-input').on('keydown', function (e) { 224 212 $('#new-card-input').on('keydown', function(e) {
if (e.which == 13) { 225 213 if (e.which == 13) {
e.preventDefault(); 226 214 e.preventDefault();
$scope.pushCard(); 227 215 $scope.pushCard();
$('#newCard').closeModal(modal_options); 228 216 $('#newCard').closeModal(modal_options);
return false; 229 217 return false;
} 230 218 }
}); 231 219 });
$('#new-card-input').on('mouseup', function () { 232 220 $('#new-card-input').on('mouseup', function() {
console.log('got selection: ' + selected_start); 233 221 console.log('got selection: ' + selected_start);
}); 234 222 });
$('button#blank-selected').click(function () { 235 223 $('button#blank-selected').click(function() {
console.log(window.getSelection()); 236 224 console.log(window.getSelection());
document.execCommand('bold'); 237 225 document.execCommand('bold');
}); 238 226 });
}); 239 227 });
//$scope.refreshCards(); 240 228 //$scope.refreshCards();
//$scope.refreshLayout(); 241 229 //$scope.refreshLayout();
$scope.$on('$destroy', function () { 242 230 $scope.$on('$destroy', function() {
ws.close(); 243 231 ws.close();
$rootScope.currentSection = {}; 244 232 $rootScope.currentSection = {};
$(document).off('keydown'); 245 233 $(document).off('keydown');
}); 246 234 });
247 235
}); 248 236 });
249 237
scripts/FlashcardDirective.js View file @ fe2c7ed
angular.module('flashy.FlashcardDirective', []). 1 1 angular.module('flashy.FlashcardDirective', []).
2 2
directive('flashcard', ['$http', '$state', '$window', 3 3 directive('flashcard', ['$http', '$state', '$window',
function($http, $state, $window) { 4 4 function($http, $state, $window) {
return { 5 5 return {
templateUrl: '/app/templates/flashcard.html', 6 6 templateUrl: '/app/templates/flashcard.html',
restrict: 'E', 7 7 restrict: 'E',
scope: { 8 8 scope: {
flashcard: '=flashcardObj', // flashcard-obj in parent html 9 9 flashcard: '=flashcardObj', // flashcard-obj in parent html
refresh: '&' // eval refresh in parent html 10 10 refresh: '&' // eval refresh in parent html
}, 11 11 },
link: function(scope, element) { 12 12 link: function(scope, element) {
/* Handles width of the card */ 13 13 /* Handles width of the card */
function refresh_width() { 14 14 function refresh_width() {
avail = $window.innerWidth - 17; 15 15 avail = $window.innerWidth - 17;
width = Math.floor(avail / Math.floor(avail / 250) - 12); 16 16 width = Math.floor(avail / Math.floor(avail / 250) - 12);
element.children().css({ 17 17 element.children().css({
width: width + 'px', 18 18 width: width + 'px',
height: (width * 3 / 5) + 'px', 19 19 height: (width * 3 / 5) + 'px',
'font-size': 100 * width / 250 + '%' 20
}); 21 20 });
}; 22 21 };
angular.element($window).bind('resize', refresh_width); 23 22 angular.element($window).bind('resize', refresh_width);
refresh_width(); 24 23 refresh_width();
scope.textPieces = []; 25 24 scope.textPieces = [];
scope.flashcard.mask.sort(function(a, b) { 26 25 scope.flashcard.mask.sort(function(a, b) {
return a[0] - b[0]; 27 26 return a[0] - b[0];
}); 28 27 });
var i = 0; 29 28 var i = 0;
scope.flashcard.mask.forEach(function(blank) { 30 29 scope.flashcard.mask.forEach(function(blank) {
scope.textPieces.push({text: scope.flashcard.text.slice(i, blank[0])}); 31 30 scope.textPieces.push({text: scope.flashcard.text.slice(i, blank[0])});
scope.textPieces.push({text: scope.flashcard.text.slice(blank[0], blank[1]), blank: true}); 32 31 scope.textPieces.push({text: scope.flashcard.text.slice(blank[0], blank[1]), blank: true});
i = blank[1]; 33 32 i = blank[1];
}); 34 33 });
scope.textPieces.push({text: scope.flashcard.text.slice(i)}); 35 34 scope.textPieces.push({text: scope.flashcard.text.slice(i)});
/* Pulls card from feed into deck */ 36 35 /* Pulls card from feed into deck */
scope.pullCard = function(flashcard) { 37 36 scope.pullCard = function(flashcard) {
if ($state.current.name == 'feed') { 38 37 if ($state.current.name == 'feed') {
$http.post('/api/flashcards/' + flashcard.id + '/pull/', flashcard). 39 38 $http.post('/api/flashcards/' + flashcard.id + '/pull/', flashcard).
success(function(data) { 40 39 success(function(data) {
console.log('pulled flashcard #' + flashcard.id); 41 40 console.log('pulled flashcard #' + flashcard.id);
scope.startShrink = true; 42 41 scope.startShrink = true;
scope.refresh(flashcard); 43 42 scope.refresh(flashcard);
}). 44 43 }).
error(function(data) { 45 44 error(function(data) {
console.log('failed to pull flashcard #' + flashcard.id); 46 45 console.log('failed to pull flashcard #' + flashcard.id);
}); 47 46 });
} 48 47 }
}; 49 48 };
50 49
/* Unpulls card from deck */ 51 50 /* Unpulls card from deck */
scope.unpullCard = function(flashcard) { 52 51 scope.unpullCard = function(flashcard) {
if ($state.current.name == 'deck') { 53 52 if ($state.current.name == 'deck') {
console.log('unpulling card...'); 54 53 console.log('unpulling card...');
55 54
$http.post('/api/flashcards/' + flashcard.id + '/unpull/', 56 55 $http.post('/api/flashcards/' + flashcard.id + '/unpull/',
flashcard). 57 56 flashcard).
success(function(data) { 58 57 success(function(data) {
console.log('card unpull success'); 59 58 console.log('card unpull success');
scope.startShrink = true; 60 59 scope.startShrink = true;
scope.refresh(flashcard); 61 60 scope.refresh(flashcard);
}). 62 61 }).
error(function(data) { 63 62 error(function(data) {
console.log('card unpull FAILURE'); 64 63 console.log('card unpull FAILURE');
}); 65 64 });
} 66 65 }
}; 67 66 };
68 67
/* Hides card from feed */ 69 68 /* Hides card from feed */
scope.hideCard = function(flashcard) { 70 69 scope.hideCard = function(flashcard) {
if ($state.current.name == 'feed') { 71 70 if ($state.current.name == 'feed') {
$http.post('/api/flashcards/' + flashcard.id + '/hide/', 72 71 $http.post('/api/flashcards/' + flashcard.id + '/hide/',
flashcard). 73 72 flashcard).
success(function(data) { 74 73 success(function(data) {
console.log('card hide success'); 75 74 console.log('card hide success');
scope.startShrink = true; 76 75 scope.startShrink = true;
scope.refresh(flashcard); 77 76 scope.refresh(flashcard);
}). 78 77 }).
error(function(data) { 79 78 error(function(data) {
console.log('card hide FAILURE'); 80 79 console.log('card hide FAILURE');
}); 81 80 });
} 82 81 }
scripts/LoginController.js View file @ fe2c7ed
angular.module('flashy.LoginController', ['ui.router']). 1 1 angular.module('flashy.LoginController', ['ui.router']).
2 2
controller('LoginController', ['$rootScope', '$scope', '$state', '$http', 'UserService', 3 3 controller('LoginController', ['$rootScope', '$scope', '$state', '$http', 'UserService',
function ($rootScope, $scope, $state, $http, UserService) { 4 4 function($rootScope, $scope, $state, $http, UserService) {
'use strict'; 5 5 'use strict';
// If we're logged in, there's nothing to do here 6 6 // If we're logged in, there's nothing to do here
if (UserService.isLoggedIn()) $state.go('addclass'); 7 7 if (UserService.isLoggedIn()) $state.go('addclass');
$scope.uniqueError = false; 8 8 $scope.uniqueError = false;
$scope.loginError = false; 9 9 $scope.loginError = false;
$scope.login = function (email, password) { 10 10 $scope.login = function(email, password) {
$http.post('/api/login/', JSON.stringify({ 11 11 $http.post('/api/login/', JSON.stringify({
'email': email, 12 12 'email': email,
'password': password 13 13 'password': password
})). 14 14 })).
success(function (data) { 15 15 success(function(data) {
UserService.login(data); 16 16 UserService.login(data);
if (angular.isDefined($scope.returnToState)) 17 17 if (angular.isDefined($scope.returnToState))
$state.go($scope.returnToState.name, $scope.returnToStateParams); 18 18 $state.go($scope.returnToState.name, $scope.returnToStateParams);
else 19 19 else
UserService.redirectToDefaultState($state); 20 20 UserService.redirectToDefaultState($state);
}). 21 21 }).
error(function (data, status, header, config) { 22 22 error(function(data, status, header, config) {
if (data.detail) { // assume 'invalid email or pass' 23 23 if (data.detail) { // assume 'invalid email or pass'
$scope.loginError = true; 24 24 $scope.loginError = true;
} 25 25 }
console.log(data); 26 26 console.log(data);
}); 27 27 });
}; 28 28 };
$scope.signUp = function (email, password) { 29 29 $scope.signUp = function(email, password) {
$http.post('/api/register/', JSON.stringify({ 30 30 $http.post('/api/register/', JSON.stringify({
'email': email, 31 31 'email': email,
'password': password 32 32 'password': password
})). 33 33 })).
success(function (data) { 34 34 success(function(data) {
UserService.login(data); 35 35 UserService.login(data);
if (angular.isDefined($scope.returnToState)) 36 36 if (angular.isDefined($scope.returnToState))
$state.go($scope.returnToState.name, $scope.returnToStateParams); 37 37 $state.go($scope.returnToState.name, $scope.returnToStateParams);
else $state.go('addclass'); 38 38 else $state.go('addclass');
39 39
}). 40 40 }).
error(function (data, status, headers, config) { 41 41 error(function(data, status, headers, config) {
console.log(data.email); 42 42 console.log(data.email);
if (data.email == 'This field is required.') { 43 43 if (data.email == 'This field is required.') {
$scope.invalid = true; 44 44 $scope.invalid = true;
$scope.uniqueError = false; 45 45 $scope.uniqueError = false;
} else if (data.email == 'This field must be unique.') { 46 46 } else if (data.email == 'This field must be unique.') {
// assume 'email not unique' error 47 47 // assume 'email not unique' error
$scope.uniqueError = true; 48 48 $scope.uniqueError = true;
$scope.invalid = false; 49 49 $scope.invalid = false;
} 50 50 }
console.log(data); 51 51 console.log(data);
}); 52 52 });
53 53
}; 54 54 };
$scope.triggerPasswordReset = function () { 55 55 $scope.triggerPasswordReset = function() {
$state.go('requestpasswordreset'); 56 56 $state.go('requestpasswordreset');
}; 57 57 };
$(document).ready(function () { 58 58 $(document).ready(function() {
$('ul.tabs').tabs(); 59 59 $('ul.tabs').tabs();
}); 60 60 });
} 61 61 }
]); 62 62 ]);
63 63
scripts/RootController.js View file @ fe2c7ed
angular.module('flashy.RootController', ['ui.router', 'ngResource']). 1 1 angular.module('flashy.RootController', ['ui.router', 'ngResource']).
2 2
controller('RootController', function ($rootScope, $resource, $scope, $state, UserService) { 3 3 controller('RootController', function($rootScope, $resource, $scope, $state, UserService) {
$rootScope.SectionResource = $resource('/api/sections/:sectionId/'); 4 4 $rootScope.SectionResource = $resource('/api/sections/:sectionId/');
window.rootscope = $rootScope; 5 5 window.rootscope = $rootScope;
window.userservice = UserService; 6 6 window.userservice = UserService;
$rootScope.currentSection = {}; 7 7 $rootScope.currentSection = {};
$scope.UserService = UserService; 8 8 $scope.UserService = UserService;
9 9
10 10
//UserService.getUserData().then(function(data) { 11 11 //UserService.getUserData().then(function(data) {
// console.log(data); 12 12 // console.log(data);
// $rootScope.user = data; 13 13 // $rootScope.user = data;
//}); 14 14 //});
$('.button-collapse').sideNav({ 15 15 $('.button-collapse').sideNav({
menuWidth: 240, // Default is 240 16 16 menuWidth: 240, // Default is 240
edge: 'left', // Choose the horizontal origin 17 17 edge: 'left', // Choose the horizontal origin
closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor 18 18 closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor
} 19 19 }
); 20 20 );
var postlogin = function (data) { 21 21 var postlogin = function(data) {
$scope.user = data; 22 22 $scope.user = data;
UserService.redirectToDefaultState($state); 23 23 UserService.redirectToDefaultState($state);
}; 24 24 };
if (UserService.isLoggedIn()) { 25 25 if (UserService.isLoggedIn()) {
postlogin(UserService.getUserData()); 26 26 postlogin(UserService.getUserData());
} else { 27 27 } else {
UserService.getUserData().then(postlogin); 28 28 UserService.getUserData().then(postlogin);
} 29 29 }
scripts/UserService.js View file @ fe2c7ed
angular.module('flashy.UserService', ['ui.router']). 1 1 angular.module('flashy.UserService', ['ui.router']).
service('UserService', function ($rootScope, $http, $q) { 2 2 service('UserService', function($rootScope, $http, $q) {
var deferred = $q.defer(); 3 3 var deferred = $q.defer();
var _user = false; 4 4 var _user = false;
$http.get('/api/me/').success(function (data) { 5 5 $http.get('/api/me/').success(function(data) {
console.log('user is logged in!'); 6 6 console.log('user is logged in!');
_user = data; 7 7 _user = data;
deferred.resolve(data); 8 8 deferred.resolve(data);
}).error(function (data) { 9 9 }).error(function(data) {
console.log(data); 10 10 console.log(data);
console.log('not logged in yet: ' + data.detail); 11 11 console.log('not logged in yet: ' + data.detail);
_user = {email: false}; 12 12 _user = {email: false};
deferred.resolve(_user); 13 13 deferred.resolve(_user);
}); 14 14 });
15 15
this.isResolved = function () { 16 16 this.isResolved = function() {
return !!_user; 17 17 return !!_user;
}; 18 18 };
this.getUserData = function () { 19 19 this.getUserData = function() {
if (this.isResolved()) return _user; 20 20 if (this.isResolved()) return _user;
else return deferred.promise; 21 21 else return deferred.promise;
}; 22 22 };
this.login = function (data) { 23 23 this.login = function(data) {
_user = data; 24 24 _user = data;
if (!data.is_confirmed) { 25 25 if (!data.is_confirmed) {
Materialize.toast('Please verify your email address!', 4000); 26 26 Materialize.toast('Please verify your email address!', 4000);
} 27 27 }
deferred.resolve(data); 28 28 deferred.resolve(data);
}; 29 29 };
this.hasVerifiedEmail = function () { 30 30 this.hasVerifiedEmail = function() {
return this.isResolved() && _user.is_confirmed; 31 31 return this.isResolved() && _user.is_confirmed;
}; 32 32 };
this.logout = function () { 33 33 this.logout = function() {
_user = false; 34 34 _user = false;
deferred.resolve({}); 35 35 deferred.resolve({});
}; 36 36 };
this.isLoggedIn = function () { 37 37 this.isLoggedIn = function() {
rv = this.isResolved() && _user.email; 38 38 rv = this.isResolved() && _user.email;
return rv; 39 39 return rv;
}; 40 40 };
this.redirectToDefaultState = function ($state) { 41 41 this.redirectToDefaultState = function($state) {
if (!this.isLoggedIn()) return $state.go('login'); 42 42 if (!this.isLoggedIn()) return $state.go('login');
if (!_user.sections.length) return $state.go('addclass'); 43 43 if (!_user.sections.length) return $state.go('addclass');
last_state = localStorage.getItem('last_state'); 44 44 last_state = localStorage.getItem('last_state');
if (last_state) return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params'))); 45 45 if (last_state) return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params')));
$state.go('feed', {sectionId: _user.sections[0].id}); 46 46 $state.go('feed', {sectionId: _user.sections[0].id});
}; 47 47 };
}); 48 48 });
49 49