Commit 065f0cdac43f2cd79a139e64a2a508a550f3bcba

Authored by Tetranoir
1 parent 40bf27d12f

node.data error and made submitting more consistent between pressing enter vs pressing submit

Showing 4 changed files with 27 additions and 7 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',
'flashy.SettingsController', 15 15 'flashy.SettingsController',
'ngCookies']). 16 16 'ngCookies']).
config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) { 17 17 config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) {
'use strict'; 18 18 'use strict';
$httpProvider.defaults.withCredentials = true; 19 19 $httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; 20 20 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 21 21 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$resourceProvider.defaults.stripTrailingSlashes = false; 22 22 $resourceProvider.defaults.stripTrailingSlashes = false;
var arrayMethods = Object.getOwnPropertyNames(Array.prototype); 23 23 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
arrayMethods.forEach(attachArrayMethodsToNodeList); 24 24 arrayMethods.forEach(attachArrayMethodsToNodeList);
function attachArrayMethodsToNodeList(methodName) { 25 25 function attachArrayMethodsToNodeList(methodName) {
if (methodName !== 'length') { 26 26 if (methodName !== 'length') {
NodeList.prototype[methodName] = Array.prototype[methodName]; 27 27 NodeList.prototype[methodName] = Array.prototype[methodName];
} 28 28 }
}; 29 29 };
30 30
$httpProvider.interceptors.push(function($q) { 31 31 $httpProvider.interceptors.push(function($q) {
return { 32 32 return {
'responseError': function(rejection) { 33 33 'responseError': function(rejection) { // need a better redirect
if (rejection.status >= 500) { 34 34 if (rejection.status >= 500) {
console.log('got error'); 35 35 console.log('got error');
console.log(rejection); 36 36 console.log(rejection);
$('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>'); 37 37 $('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>');
} 38 38 }
return $q.reject(rejection); 39 39 return $q.reject(rejection);
} 40 40 }
}; 41 41 };
}); 42 42 });
$locationProvider.html5Mode(true); 43 43 $locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/404'); 44 44 $urlRouterProvider.otherwise('/404');
var auth_resolve = { 45 45 var auth_resolve = {
authorize: function($q, $state, $stateParams, UserService) { 46 46 authorize: function($q, $state, $stateParams, UserService) {
console.log('resolving user before continuing'); 47 47 console.log('resolving user before continuing');
var redirectAsNeeded = function() { 48 48 var redirectAsNeeded = function() {
if (!UserService.isLoggedIn()) { 49 49 if (!UserService.isLoggedIn()) {
console.log(UserService.getUserData()); 50 50 console.log(UserService.getUserData());
console.log('making the user log in'); 51 51 console.log('making the user log in');
$state.go('login'); 52 52 $state.go('login');
} 53 53 }
if (!UserService.authorizedFor($state, $stateParams)) { 54 54 if (!UserService.authorizedFor($state, $stateParams)) {
$state.go('addclass'); 55 55 $state.go('addclass');
} 56 56 }
}; 57 57 };
if (UserService.isResolved()) return redirectAsNeeded(); 58 58 if (UserService.isResolved()) return redirectAsNeeded();
return UserService.getUserData().then(redirectAsNeeded); 59 59 return UserService.getUserData().then(redirectAsNeeded);
} 60 60 }
}; 61 61 };
$stateProvider. 62 62 $stateProvider.
state('login', { 63 63 state('login', {
url: '/login', 64 64 url: '/login',
templateUrl: 'templates/login.html', 65 65 templateUrl: 'templates/login.html',
controller: 'LoginController' 66 66 controller: 'LoginController'
}). 67 67 }).
state('logout', { 68 68 state('logout', {
resolve: auth_resolve, 69 69 resolve: auth_resolve,
url: '/logout', 70 70 url: '/logout',
templateUrl: 'templates/logout.html', 71 71 templateUrl: 'templates/logout.html',
controller: 'LogoutController' 72 72 controller: 'LogoutController'
}). 73 73 }).
state('root', { 74 74 state('root', {
resolve: auth_resolve, 75 75 resolve: auth_resolve,
url: '/', 76 76 url: '/',
controller: 'RootController' 77 77 controller: 'RootController'
}). 78 78 }).
state('feed', { 79 79 state('feed', {
resolve: auth_resolve, 80 80 resolve: auth_resolve,
url: '/feed/{sectionId}', 81 81 url: '/feed/{sectionId}',
templateUrl: 'templates/feed.html', 82 82 templateUrl: 'templates/feed.html',
controller: 'FeedController' 83 83 controller: 'FeedController'
}). 84 84 }).
state('cardlist', { 85 85 state('cardlist', {
resolve: auth_resolve, 86 86 resolve: auth_resolve,
url: '/cards/{sectionId}', 87 87 url: '/cards/{sectionId}',
templateUrl: 'templates/cardlist.html', 88 88 templateUrl: 'templates/cardlist.html',
controller: 'CardListController' 89 89 controller: 'CardListController'
}). 90 90 }).
state('addclass', { 91 91 state('addclass', {
resolve: auth_resolve, 92 92 resolve: auth_resolve,
url: '/addclass', 93 93 url: '/addclass',
templateUrl: 'templates/addclass.html', 94 94 templateUrl: 'templates/addclass.html',
controller: 'ClassAddController' 95 95 controller: 'ClassAddController'
}). 96 96 }).
state('deck', { 97 97 state('deck', {
resolve: auth_resolve, 98 98 resolve: auth_resolve,
url: '/deck/{sectionId}', 99 99 url: '/deck/{sectionId}',
templateUrl: 'templates/deck.html', 100 100 templateUrl: 'templates/deck.html',
controller: 'DeckController' 101 101 controller: 'DeckController'
}). 102 102 }).
state('study', { 103 103 state('study', {
resolve: auth_resolve, 104 104 resolve: auth_resolve,
url: '/study', 105 105 url: '/study',
templateUrl: 'templates/study.html', 106 106 templateUrl: 'templates/study.html',
controller: 'StudyController' 107 107 controller: 'StudyController'
}). 108 108 }).
state('flashcard', { 109 109 state('flashcard', {
resolve: auth_resolve, 110 110 resolve: auth_resolve,
url: '/flashcard', 111 111 url: '/flashcard',
templateUrl: 'templates/flashcard.html', 112 112 templateUrl: 'templates/flashcard.html',
controller: 'FlashcardController' 113 113 controller: 'FlashcardController'
}). 114 114 }).
state('settings', { 115 115 state('settings', {
resolve: auth_resolve, 116 116 resolve: auth_resolve,
url: '/settings', 117 117 url: '/settings',
templateUrl: 'templates/settings.html', 118 118 templateUrl: 'templates/settings.html',
controller: 'SettingsController' 119 119 controller: 'SettingsController'
}). 120 120 }).
state('requestpasswordreset', { 121 121 state('requestpasswordreset', {
url: '/requestpasswordreset', 122 122 url: '/requestpasswordreset',
templateUrl: 'templates/requestpasswordreset.html', 123 123 templateUrl: 'templates/requestpasswordreset.html',
controller: 'RequestResetController' 124 124 controller: 'RequestResetController'
}). 125 125 }).
state('resetpassword', { 126 126 state('resetpassword', {
url: '/resetpassword/{uid}/{token}', 127 127 url: '/resetpassword/{uid}/{token}',
templateUrl: 'templates/resetpassword.html', 128 128 templateUrl: 'templates/resetpassword.html',
controller: 'ResetPasswordController' 129 129 controller: 'ResetPasswordController'
}). 130 130 }).
state('verifyemail', { 131 131 state('verifyemail', {
resolve: auth_resolve, 132 132 resolve: auth_resolve,
url: '/verifyemail/{key}', 133 133 url: '/verifyemail/{key}',
templateUrl: 'templates/verifyemail.html', 134 134 templateUrl: 'templates/verifyemail.html',
controller: 'VerifyEmailController' 135 135 controller: 'VerifyEmailController'
}). 136 136 }).
state('404', { 137 137 state('404', {
url: '/404', 138 138 url: '/404',
template: "<h1>This page doesn't exist!</h1>" 139 139 template: "<h1>This page doesn't exist!</h1>"
}); 140 140 });
}). 141 141 }).
run(function($rootScope, $state, $stateParams, $location, UserService) { 142 142 run(function($rootScope, $state, $stateParams, $location, UserService) {
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { 143 143 $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
console.log('failed to change state: ' + error); 144 144 console.log('failed to change state: ' + error);
$state.go('login'); 145 145 $state.go('login');
}); 146 146 });
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { 147 147 $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) { 148 148 if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) {
localStorage.setItem('last_state', toState.name); 149 149 localStorage.setItem('last_state', toState.name);
localStorage.setItem('last_state_params', JSON.stringify(toParams)); 150 150 localStorage.setItem('last_state_params', JSON.stringify(toParams));
} 151 151 }
}); 152 152 });
}); 153 153 });
scripts/FeedController.js View file @ 065f0cd
angular.module('flashy.FeedController', ['ui.router', 'ngAnimate']). 1 1 angular.module('flashy.FeedController', ['ui.router', 'ngAnimate']).
2 2
controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, UserService) { 3 3 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, 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.cardCols = []; // organized data 8 8 $scope.cardCols = []; // organized data
$scope.numCols = 0; 9 9 $scope.numCols = 0;
10 10
function calculate_cols() { 11 11 function calculate_cols() {
var avail = $window.innerWidth - 17; 12 12 var avail = $window.innerWidth - 17;
return Math.max(1, Math.floor(avail / 250)); 13 13 return Math.max(1, Math.floor(avail / 250));
} 14 14 }
15 15
$scope.refreshColumnWidth = function() { 16 16 $scope.refreshColumnWidth = function() {
console.log('refreshing column width'); 17 17 console.log('refreshing column width');
avail = $window.innerWidth - 17; 18 18 avail = $window.innerWidth - 17;
width = Math.floor(avail / Math.floor(avail / 250)); 19 19 width = Math.floor(avail / Math.floor(avail / 250));
$('.cardColumn').css({ 20 20 $('.cardColumn').css({
width: width + 'px', 21 21 width: width + 'px',
'font-size': 100 * width / 250 + '%' 22 22 'font-size': 100 * width / 250 + '%'
}); 23 23 });
$('.cardColumn .card.flashy').css({ 24 24 $('.cardColumn .card.flashy').css({
width: width - 12 + 'px', 25 25 width: width - 12 + 'px',
height: (width * 3 / 5) + 'px' 26 26 height: (width * 3 / 5) + 'px'
}); 27 27 });
}; 28 28 };
29 29
$scope.refreshLayout = function() { 30 30 $scope.refreshLayout = function() {
// check if we actually need to refresh the whole layout 31 31 // check if we actually need to refresh the whole layout
if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth(); 32 32 if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth();
$scope.numCols = calculate_cols(); 33 33 $scope.numCols = calculate_cols();
console.log('refreshing layout for ' + $scope.numCols + ' columns'); 34 34 console.log('refreshing layout for ' + $scope.numCols + ' columns');
$scope.cardCols = []; 35 35 $scope.cardCols = [];
var cols = []; 36 36 var cols = [];
for (i = 0; i < $scope.numCols; i++) cols.push([]); 37 37 for (i = 0; i < $scope.numCols; i++) cols.push([]);
$scope.cards.forEach(function(card, i) { 38 38 $scope.cards.forEach(function(card, i) {
cols[i % $scope.numCols].push(card); 39 39 cols[i % $scope.numCols].push(card);
}); 40 40 });
// wait until the next digest cycle to update cardCols 41 41 // wait until the next digest cycle to update cardCols
42 42
$timeout(function() { 43 43 $timeout(function() {
$scope.cardCols = cols; 44 44 $scope.cardCols = cols;
$timeout($scope.refreshColumnWidth); 45 45 $timeout($scope.refreshColumnWidth);
}); 46 46 });
47 47
}; 48 48 };
49 49
angular.element($window).bind('resize', $scope.refreshLayout); 50 50 angular.element($window).bind('resize', $scope.refreshLayout);
51 51
$scope.refreshCards = function() { 52 52 $scope.refreshCards = function() {
$http.get('/api/sections/' + sectionId + '/feed/'). 53 53 $http.get('/api/sections/' + sectionId + '/feed/').
success(function(data) { 54 54 success(function(data) {
console.log(data); 55 55 console.log(data);
$scope.cards = data; 56 56 $scope.cards = data;
$scope.refreshLayout(); 57 57 $scope.refreshLayout();
console.log('success in refresh cards...'); 58 58 console.log('success in refresh cards...');
}). 59 59 }).
error(function(err) { 60 60 error(function(err) {
console.log('refresh fail'); 61 61 console.log('refresh fail');
}); 62 62 });
}; 63 63 };
64 64
$scope.add = function(card) { 65 65 $scope.add = function(card) {
var colNum = 0; 66 66 var colNum = 0;
var lowestCol = {}; 67 67 var lowestCol = {};
var lowestColLen = Infinity; 68 68 var lowestColLen = Infinity;
while (colNum < $scope.numCols) { 69 69 while (colNum < $scope.numCols) {
if ($scope.cardCols[colNum].length == 0) { 70 70 if ($scope.cardCols[colNum].length == 0) {
lowestCol = $scope.cardCols[colNum]; 71 71 lowestCol = $scope.cardCols[colNum];
break; 72 72 break;
} else if ($scope.cardCols[colNum].length < lowestColLen) { 73 73 } else if ($scope.cardCols[colNum].length < lowestColLen) {
lowestCol = $scope.cardCols[colNum]; 74 74 lowestCol = $scope.cardCols[colNum];
lowestColLen = $scope.cardCols[colNum].length; 75 75 lowestColLen = $scope.cardCols[colNum].length;
} 76 76 }
colNum++; 77 77 colNum++;
} 78 78 }
/*if (colNum == $scope.numCols) { 79 79 /*if (colNum == $scope.numCols) {
colNum = Math.floor(Math.random() * $scope.numCols); 80 80 colNum = Math.floor(Math.random() * $scope.numCols);
} 81 81 }
console.log('adding card to column ' + colNum);*/ 82 82 console.log('adding card to column ' + colNum);*/
console.log(card); 83 83 console.log(card);
$scope.cards.push(data); 84 84 $scope.cards.push(data);
$timeout(function() { 85 85 $timeout(function() {
lowestCol.unshift(card); 86 86 lowestCol.unshift(card);
$timeout($scope.refreshColumnWidth); 87 87 $timeout($scope.refreshColumnWidth);
}); 88 88 });
}; 89 89 };
90 90
$scope.hide = function(card) { 91 91 $scope.hide = function(card) {
console.log('hiding card'); 92 92 console.log('hiding card');
var found = -1; 93 93 var found = -1;
for (i = 0; i < $scope.cardCols.length; i++) { 94 94 for (i = 0; i < $scope.cardCols.length; i++) {
found = $scope.cardCols[i].indexOf(card); 95 95 found = $scope.cardCols[i].indexOf(card);
if (found != -1) { 96 96 if (found != -1) {
$timeout(function() { 97 97 $timeout(function() {
console.log('card to hide, found'); 98 98 console.log('card to hide, found');
}); 99 99 });
$scope.cardCols[i].splice(found, 1); 100 100 $scope.cardCols[i].splice(found, 1);
return; 101 101 return;
} 102 102 }
} 103 103 }
console.log('Error finding card to hide:'); 104 104 console.log('Error finding card to hide:');
console.log(card); 105 105 console.log(card);
}; 106 106 };
107 107
var loc = window.location, new_uri; 108 108 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 109 109 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 110 110 new_uri = 'wss:';
} else { 111 111 } else {
new_uri = 'ws:'; 112 112 new_uri = 'ws:';
} 113 113 }
new_uri += '//' + loc.host; 114 114 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast'); 115 115 var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast');
116 116
ws.onopen = function() { 117 117 ws.onopen = function() {
console.log('websocket connected'); 118 118 console.log('websocket connected');
}; 119 119 };
ws.onmessage = function(e) { 120 120 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 121 121 console.log('got websocket message ' + e.data);
data = JSON.parse(e.data); 122 122 data = JSON.parse(e.data);
if (data.event_type == 'new_card') { 123 123 if (data.event_type == 'new_card') {
$scope.add(data.flashcard); 124 124 $scope.add(data.flashcard);
} 125 125 }
}; 126 126 };
ws.onerror = function(e) { 127 127 ws.onerror = function(e) {
console.error(e); 128 128 console.error(e);
}; 129 129 };
ws.onclose = function(e) { 130 130 ws.onclose = function(e) {
console.log('connection closed'); 131 131 console.log('connection closed');
}; 132 132 };
133 133
134 var resetModal = function() {
135 $('#new-card-input').html('');
136 $('#newCard').closeModal(modal_options);
137 }
138
$scope.pushCard = function() { 134 139 $scope.pushCard = function() {
var i = 0; 135 140 var i = 0;
var blanks = []; 136 141 var blanks = [];
$('#new-card-input')[0].childNodes.forEach(function(node) { 137 142 $('#new-card-input')[0].childNodes.forEach(function(node) {
143 if (typeof node.data == 'undefined') {
144 console.log('undefined node');
145 return resetModal();
146 }
node = $(node)[0]; 138 147 node = $(node)[0];
console.log(node); 139 148 console.log(node);
if (node.tagName == 'B') { 140 149 if (node.tagName == 'B') {
text = $(node).text(); 141 150 text = $(node).text();
blanks.push([i, i + text.length]); 142 151 blanks.push([i, i + text.length]);
i += text.length; 143 152 i += text.length;
} else { 144 153 } else {
i += node.data.length; 145 154 i += node.data.length;
} 146 155 }
}); 147 156 });
var myCard = { 148 157 var myCard = {
'text': $('#new-card-input').text(), 149 158 'text': $('#new-card-input').text().trim(),
'mask': blanks, 150 159 'mask': blanks,
section: sectionId 151 160 section: sectionId
}; 152 161 };
162 if (myCard.text == '') {
163 console.log('blank flashcard not pushed:' + myCard.text);
164 return resetModal();
165 }
$http.post('/api/flashcards/', myCard). 153 166 $http.post('/api/flashcards/', myCard).
success(function(data) { 154 167 success(function(data) {
console.log('flashcard push succeeded'); 155 168 console.log('flashcard pushed: ' + myCard.text);
if (!UserService.hasVerifiedEmail()) { 156 169 if (!UserService.hasVerifiedEmail()) {
Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000); 157 170 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
} 158 171 }
159 172
}). 160 173 }).
error(function(error) { 161 174 error(function(error) {
console.log('something went wrong pushing a card!'); 162 175 console.log('something went wrong pushing a card!');
}); 163 176 });
177 return resetModal();
}; 164 178 };
165 179
/* Key bindings for the whole feed window. Hotkey it up! */ 166 180 /* Key bindings for the whole feed window. Hotkey it up! */
var listenForC = true; 167 181 var listenForC = true;
168 182
// Need to pass these options into openmodal and leanmodal, 169 183 // Need to pass these options into openmodal and leanmodal,
// otherwise the ready handler doesn't get called 170 184 // otherwise the ready handler doesn't get called
171 185
modal_options = { 172 186 modal_options = {
dismissible: true, // Modal can be dismissed by clicking outside of the modal 173 187 dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: 0, // Opacity of modal background 174 188 opacity: 0, // Opacity of modal background
in_duration: 300, // Transition in duration 175 189 in_duration: 300, // Transition in duration
out_duration: 200, // Transition out duration 176 190 out_duration: 200, // Transition out duration
ready: function() { 177 191 ready: function() {
listenForC = false; 178 192 listenForC = false;
console.log('modal OPENING'); 179 193 console.log('modal OPENING');
$('#new-card-input').focus(); 180 194 $('#new-card-input').focus();
}, 181 195 },
complete: function() { 182 196 complete: function() {
listenForC = true; 183 197 listenForC = true;
console.log('modal done, closing'); 184 198 console.log('modal done, closing');
$('#new-card-input').blur(); 185 199 $('#new-card-input').blur();
} 186 200 }
}; 187 201 };
188 202
$(document).keydown(function(e) { 189 203 $(document).keydown(function(e) {
var keyed = e.which; 190 204 var keyed = e.which;
if (keyed == 67 && listenForC) { // "c" for compose 191 205 if (keyed == 67 && listenForC) { // "c" for compose
$('#newCard').openModal(modal_options); 192 206 $('#newCard').openModal(modal_options);
e.preventDefault(); 193 207 e.preventDefault();
listenForC = false; 194 208 listenForC = false;
return false; 195 209 return false;
} else if (keyed == 27) { // clear on ESC 196 210 } else if (keyed == 27) { // clear on ESC
listenForC = true; 197 211 listenForC = true;
document.getElementById('new-card-input').value = ''; 198 212 document.getElementById('new-card-input').value = '';
} 199 213 }
}); 200 214 });
$(document).ready(function() { 201 215 $(document).ready(function() {
$('.tooltipped').tooltip({delay: 50}); 202 216 $('.tooltipped').tooltip({delay: 50});
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered 203 217 // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
$('.modal-trigger').leanModal(modal_options); 204 218 $('.modal-trigger').leanModal(modal_options);
$('#new-card-input').on('keydown', function(e) { 205 219 $('#new-card-input').on('keydown', function(e) {
if (e.which == 13) { 206 220 if (e.which == 13) {
e.preventDefault(); 207 221 e.preventDefault();
$scope.pushCard(); 208 222 $scope.pushCard();
$('#new-card-input').html(''); 209
$('#newCard').closeModal(modal_options); 210
listenForC = true; 211 223 listenForC = true;
return false; 212 224 return false;
} 213 225 }
}); 214 226 });
$('button#blank-selected').click(function() { 215 227 $('button#blank-selected').click(function() {
console.log(window.getSelection()); 216 228 console.log(window.getSelection());
document.execCommand('bold'); 217 229 document.execCommand('bold');
}); 218 230 });
}); 219 231 });
$scope.refreshCards(); 220 232 $scope.refreshCards();
styles/flashy.css View file @ 065f0cd
๏ปฟ.no-user-select { 1 1 ๏ปฟ.no-user-select {
-moz-user-select: none; 2 2 -moz-user-select: none;
-webkit-user-select: none; 3 3 -webkit-user-select: none;
-ms-user-select: none; 4 4 -ms-user-select: none;
user-select: none; 5 5 user-select: none;
} 6 6 }
7 7
.angucomplete-dropdown { 8 8 .angucomplete-dropdown {
border-color: #ececec; 9 9 border-color: #ececec;
border-width: 1px; 10 10 border-width: 1px;
border-style: solid; 11 11 border-style: solid;
border-radius: 2px; 12 12 border-radius: 2px;
/*width: 250px;*/ 13 13 /*width: 250px;*/
padding: 6px; 14 14 padding: 6px;
cursor: pointer; 15 15 cursor: pointer;
z-index: 9999; 16 16 z-index: 9999;
position: absolute; 17 17 position: absolute;
/*top: 32px; 18 18 /*top: 32px;
left: 0px; 19 19 left: 0px;
*/ 20 20 */
margin-top: -6px; 21 21 margin-top: -6px;
background-color: #ffffff; 22 22 background-color: #ffffff;
} 23 23 }
24 24
.angucomplete-description { 25 25 .angucomplete-description {
font-size: 14px; 26 26 font-size: 14px;
} 27 27 }
28 28
.angucomplete-row { 29 29 .angucomplete-row {
padding: 5px; 30 30 padding: 5px;
color: #000000; 31 31 color: #000000;
margin-bottom: 4px; 32 32 margin-bottom: 4px;
clear: both; 33 33 clear: both;
} 34 34 }
35 35
.angucomplete-selected-row { 36 36 .angucomplete-selected-row {
background-color: #aaaaff; 37 37 background-color: #aaaaff;
} 38 38 }
39 39
/*.container .row {*/ 40 40 /*.container .row {*/
/*margin-left: 0;*/ 41 41 /*margin-left: 0;*/
/*margin-right: 0;*/ 42 42 /*margin-right: 0;*/
/*}*/ 43 43 /*}*/
44 44
/* Flashcard directive css */ 45 45 /* Flashcard directive css */
.card { 46 46 .card {
word-wrap: break-word; 47 47 word-wrap: break-word;
} 48 48 }
49 49
.card.flashy { 50 50 .card.flashy {
background-color: #fff; 51 51 background-color: #fff;
font-family: 'Titillium Web', sans-serif; 52 52 font-family: 'Titillium Web', sans-serif;
float: left; 53 53 float: left;
text-align: center; 54 54 text-align: center;
margin: 6px; 55 55 margin: 6px;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1); 56 56 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1);
} 57 57 }
58 58
.card.flashy.shrinky { 59 59 .card.flashy.shrinky {
height: 0; 60 60 height: 0;
opacity: 0; 61 61 opacity: 0;
overflow: hidden; 62 62 overflow: hidden;
} 63 63 }
64 64
.card-overlay { 65 65 .card-overlay {
cursor: pointer; 66 66 cursor: pointer;
left: 0; 67 67 left: 0;
opacity: 0; 68 68 opacity: 0;
position: absolute; 69 69 position: absolute;
top: 0; 70 70 top: 0;
transition: visibility 0s cubic-bezier(0, 0, 0.6, 1) 0.2s, 71 71 transition: visibility 0s cubic-bezier(0, 0, 0.6, 1) 0.2s,
opacity 0.2s cubic-bezier(0, 0, 0.6, 1); 72 72 opacity 0.2s cubic-bezier(0, 0, 0.6, 1);
/* animation effect to appear on off-hover */ 73 73 /* animation effect to appear on off-hover */
visibility: hidden; 74 74 visibility: hidden;
height: 100%; 75 75 height: 100%;
width: 100%; 76 76 width: 100%;
} 77 77 }
78 78
.card-overlay i { 79 79 .card-overlay i {
color: #FFF; 80 80 color: #FFF;
left: 50%; 81 81 left: 50%;
position: absolute; 82 82 position: absolute;
top: 50%; 83 83 top: 50%;
transform: translate(-50%, -50%); 84 84 transform: translate(-50%, -50%);
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 85 85 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
} 86 86 }
87 87
.center-me:hover i { 88 88 .center-me:hover i {
text-shadow: 0 0 15px rgba(255, 255, 255, 0.9); 89 89 text-shadow: 0 0 15px rgba(255, 255, 255, 0.9);
} 90 90 }
91 91
.card:hover .card-overlay { 92 92 .card:hover .card-overlay {
opacity: 1.0; 93 93 opacity: 1.0;
transition-delay: 0s; /* animation effect to appear on hover */ 94 94 transition-delay: 0s; /* animation effect to appear on hover */
visibility: visible; 95 95 visibility: visible;
} 96 96 }
97 97
.top-box { 98 98 .top-box {
background-color: rgba(0, 184, 76, 0.4); 99 99 background-color: rgba(0, 184, 76, 0.4);
height: 65%; 100 100 height: 65%;
position: relative; 101 101 position: relative;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 102 102 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 100%; 103 103 width: 100%;
} 104 104 }
105 105
.top-box:hover { 106 106 .top-box:hover {
background-color: rgba(0, 184, 76, 0.5); 107 107 background-color: rgba(0, 184, 76, 0.5);
} 108 108 }
109 109
.bottom-box { 110 110 .bottom-box {
height: 35%; 111 111 height: 35%;
width: 100%; 112 112 width: 100%;
} 113 113 }
114 114
.left-box { 115 115 .left-box {
background-color: rgba(119, 146, 255, 0.5); 116 116 background-color: rgba(119, 146, 255, 0.5);
float: left; 117 117 float: left;
position: relative; 118 118 position: relative;
height: 100%; 119 119 height: 100%;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 120 120 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 50%; 121 121 width: 50%;
} 122 122 }
123 123
.left-box:hover { 124 124 .left-box:hover {
background-color: rgba(119, 146, 255, 0.6); 125 125 background-color: rgba(119, 146, 255, 0.6);
} 126 126 }
127 127
.right-box { 128 128 .right-box {
background-color: rgba(255, 62, 76, 0.5); 129 129 background-color: rgba(255, 62, 76, 0.5);
float: right; 130 130 float: right;
height: 100%; 131 131 height: 100%;
position: relative; 132 132 position: relative;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 133 133 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 50%; 134 134 width: 50%;
} 135 135 }
136 136
.right-box:hover { 137 137 .right-box:hover {
background-color: rgba(255, 62, 76, 0.6); 138 138 background-color: rgba(255, 62, 76, 0.6);
} 139 139 }
140 140
.center-me { 141 141 .center-me {
height: 100%; 142 142 height: 100%;
margin: 0 auto; 143 143 margin: 0 auto;
text-align: center; 144 144 text-align: center;
vertical-align: middle; 145 145 vertical-align: middle;
width: 100%; 146 146 width: 100%;
} 147 147 }
148 148
/* Card Colors */ 149 149 /* Card Colors */
.card.flashy.cardcolor-blue div { 150 150 .card.flashy.cardcolor-blue div {
background-color: rgba(119, 158, 203, 0.5) !important; 151 151 background-color: rgba(119, 158, 203, 0.5) !important;
} 152 152 }
153 153
.cardcolor-red div { 154 154 .cardcolor-red div {
background-color: rgba(255, 105, 97, 0.5) !important; 155 155 background-color: rgba(255, 105, 97, 0.5) !important;
} 156 156 }
157 157
.cardcolor-green div { 158 158 .cardcolor-green div {
background-color: rgba(119, 190, 119, 0.5) !important; 159 159 background-color: rgba(119, 190, 119, 0.5) !important;
} 160 160 }
161 161
.cardcolor-yellow div { 162 162 .cardcolor-yellow div {
background-color: rgba(253, 253, 150, 0.5) !important; 163 163 background-color: rgba(253, 253, 150, 0.5) !important;
} 164 164 }
165 165
/* Card Colors END */ 166 166 /* Card Colors END */
167 167
.modal.bottom-sheet { 168 168 .modal.bottom-sheet {
max-width: 600px; 169 169 max-width: 600px;
margin-left: auto; 170 170 margin-left: auto;
margin-right: auto; 171 171 margin-right: auto;
} 172 172 }
173 173
174 .feed-modal-input {
175 background-color: #D3D3D3;
176 //border-style: solid;
177 //border-width: 1px;
178 box-shadow: 2px 2px 5px #888888;
179 height: 24px;
180 }
181
#newCard input[type=text] { 174 182 #newCard input[type=text] {
height: 3rem !important; 175 183 height: 3rem !important;
} 176 184 }
177 185
.input-field label { 178 186 .input-field label {
color: #00b3c2; 179 187 color: #00b3c2;
} 180 188 }
181 189
/* label focus color */ 182 190 /* label focus color */
.input-field input[type]:focus + label { 183 191 .input-field input[type]:focus + label {
color: #00b3c2; 184 192 color: #00b3c2;
} 185 193 }
186 194
/* label underline focus color */ 187 195 /* label underline focus color */
.input-field input[type]:focus { 188 196 .input-field input[type]:focus {
border-bottom: 1px solid #00b3c2; 189 197 border-bottom: 1px solid #00b3c2;
box-shadow: 0 1px 0 0 #b388ff; 190 198 box-shadow: 0 1px 0 0 #b388ff;
} 191 199 }
192 200
/* valid color */ 193 201 /* valid color */
.input-field input[type].valid { 194 202 .input-field input[type].valid {
border-bottom: 1px solid #00c28f; 195 203 border-bottom: 1px solid #00c28f;
box-shadow: 0 1px 0 0 #673ab7; 196 204 box-shadow: 0 1px 0 0 #673ab7;
} 197 205 }
198 206
/* invalid color */ 199 207 /* invalid color */
.input-field input[type].invalid { 200 208 .input-field input[type].invalid {
border-bottom: 1px solid #673ab7; 201 209 border-bottom: 1px solid #673ab7;
box-shadow: 0 1px 0 0 #673ab7; 202 210 box-shadow: 0 1px 0 0 #673ab7;
} 203 211 }
204 212
/* icon prefix focus color */ 205 213 /* icon prefix focus color */
.input-field .prefix.active { 206 214 .input-field .prefix.active {
color: #b388ff; 207 215 color: #b388ff;
} 208 216 }
209 217
/* label focus color */ 210 218 /* label focus color */
.input-field textarea[type]:focus + label { 211 219 .input-field textarea[type]:focus + label {
color: #b388ff; 212 220 color: #b388ff;
} 213 221 }
214 222
/* label underline focus color */ 215 223 /* label underline focus color */
.input-field textarea[type]:focus { 216 224 .input-field textarea[type]:focus {
border-bottom: 1px solid #00b3c2; 217 225 border-bottom: 1px solid #00b3c2;
box-shadow: 0 1px 0 0 #b388ff; 218 226 box-shadow: 0 1px 0 0 #b388ff;
} 219 227 }
220 228
body { 221 229 body {
background-color: #e8e8e8; 222 230 background-color: #e8e8e8;
overflow-x: hidden; 223 231 overflow-x: hidden;
font-family: 'Titillium Web', sans-serif; 224 232 font-family: 'Titillium Web', sans-serif;
height: 100%; 225 233 height: 100%;
} 226 234 }
html { 227 235 html {
background: transparent; 228 236 background: transparent;
height: 100%; 229 237 height: 100%;
} 230 238 }
231 239
.btn { 232 240 .btn {
background-color: #00b3c2; 233 241 background-color: #00b3c2;
} 234 242 }
235 243
.btn:hover { 236 244 .btn:hover {
background-color: #0097cb; 237 245 background-color: #0097cb;
} 238 246 }
239 247
.btn-floating { 240 248 .btn-floating {
background-color: #00b3c2; 241 249 background-color: #00b3c2;
} 242 250 }
243 251
.btn-floating:hover { 244 252 .btn-floating:hover {
background-color: #0097cb; 245 253 background-color: #0097cb;
} 246 254 }
247 255
.toggley { 248 256 .toggley {
float: left; 249 257 float: left;
margin: 10px; 250 258 margin: 10px;
} 251 259 }
252 260
#logo-container { 253 261 #logo-container {
margin-bottom: 18px; 254 262 margin-bottom: 18px;
} 255 263 }
256 264
#lean-overlay { 257 265 #lean-overlay {
display: none !important; 258 266 display: none !important;
} 259 267 }
260 268
nav { 261 269 nav {
background-color: #d2143f !important; 262 270 background-color: #d2143f !important;
} 263 271 }
264 272
main { 265 273 main {
min-height: 145px; 266 274 min-height: 145px;
} 267 275 }
268 276
.side-nav .collapsible-body { 269 277 .side-nav .collapsible-body {
width: 100%; 270 278 width: 100%;
} 271 279 }
272 280
.side-nav .collapsible-body li.active, .side-nav.fixed .collapsible-body li.active { 273 281 .side-nav .collapsible-body li.active, .side-nav.fixed .collapsible-body li.active {
background-color: #00b3c2; 274 282 background-color: #00b3c2;
} 275 283 }
276 284
nav .button-collapse { 277 285 nav .button-collapse {
margin: 0 20px; 278 286 margin: 0 20px;
} 279 287 }
280 288
.collapsible-body i { 281 289 .collapsible-body i {
font-size: 1rem !important; 282 290 font-size: 1rem !important;
} 283 291 }
284 292
.tabs .tab a { 285 293 .tabs .tab a {
color: #00b3c2; 286 294 color: #00b3c2;
} 287 295 }
288 296
.tabs .tab a:hover { 289 297 .tabs .tab a:hover {
color: #0041dd; 290 298 color: #0041dd;
} 291 299 }
292 300
.tabs .indicator { 293 301 .tabs .indicator {
border-bottom: 1px solid #00b3c2; 294 302 border-bottom: 1px solid #00b3c2;
} 295 303 }
296 304
h2 { 297 305 h2 {
text-align: center; 298 306 text-align: center;
} 299 307 }
300 308
md-content.md-default-theme { 301 309 md-content.md-default-theme {
background-color: rgba(255, 255, 255, 0); 302 310 background-color: rgba(255, 255, 255, 0);
border: 1px solid #fff; 303 311 border: 1px solid #fff;
} 304 312 }
305 313
/*#sidenav-overlay { 306 314 /*#sidenav-overlay {
background-color: rgba(0, 0, 0, 0) !important; 307 315 background-color: rgba(0, 0, 0, 0) !important;
}*/ 308 316 }*/
.card-content { 309 317 .card-content {
width: 100%; 310 318 width: 100%;
} 311 319 }
312 320
.valign-wrapper { 313 321 .valign-wrapper {
height: 100%; 314 322 height: 100%;
} 315 323 }
316 324
.toast { 317 325 .toast {
height: 100px; 318 326 height: 100px;
width: 300px; 319 327 width: 300px;
line-height: 20px; 320 328 line-height: 20px;
max-height: 100px; 321 329 max-height: 100px;
word-wrap: normal; 322 330 word-wrap: normal;
} 323 331 }
324 332
[ng-cloak] { 325 333 [ng-cloak] {
display: none !important; 326 334 display: none !important;
} 327 335 }
328 336
.cardColumn { 329 337 .cardColumn {
float: left; 330 338 float: left;
} 331 339 }
332 340
/* Animation CSS, http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html */ 333 341 /* Animation CSS, http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html */
.repeated-card.ng-enter, 334 342 .repeated-card.ng-enter,
templates/feed.html View file @ 065f0cd
<div class="row"> 1 1 <div class="row">
<h2 ng-cloak ng-show="cards.length == 0">No cards. Be the first one to add a card!</h2> 2 2 <h2 ng-cloak ng-show="cards.length == 0">No cards. Be the first one to add a card!</h2>
3 3
<div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="cards === false"> 4 4 <div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="cards === false">
<div class="indeterminate"></div> 5 5 <div class="indeterminate"></div>
</div> 6 6 </div>
<div class="cardColumn" ng-repeat="col in cardCols"> 7 7 <div class="cardColumn" ng-repeat="col in cardCols">
<div class="repeated-card" ng-repeat="card in col"> 8 8 <div class="repeated-card" ng-repeat="card in col">
<flashcard flashcard-obj="card" refresh="hide(card)"/> 9 9 <flashcard flashcard-obj="card" refresh="hide(card)"/>
</div> 10 10 </div>
</div> 11 11 </div>
12 12
<!--<div class="cardColumn" ng-repeat="col in cardCols"> 13 13 <!--<div class="cardColumn" ng-repeat="col in cardCols">
<flashcard flashcard-obj="card" ng-repeat="card in col"/> 14 14 <flashcard flashcard-obj="card" ng-repeat="card in col"/>
</div>--> 15 15 </div>-->
</div> 16 16 </div>
17 17
18 18
<!--Lil plus button in corner--> 19 19 <!--Lil plus button in corner-->
<div class="fixed-action-btn" style="bottom: 96px; right: 24px;"> 20 20 <div class="fixed-action-btn" style="bottom: 96px; right: 24px;">
<a data-target="newCard" class="btn-floating btn-large modal-trigger tooltipped" href="#newCard" data-position="left" 21 21 <a data-target="newCard" class="btn-floating btn-large modal-trigger tooltipped" href="#newCard" data-position="left"
data-delay="50" 22 22 data-delay="50"
data-tooltip="(C)ompose"> 23 23 data-tooltip="(C)ompose">
<i class="large mdi-content-add"></i> 24 24 <i class="large mdi-content-add"></i>
</a> 25 25 </a>
</div> 26 26 </div>
27 27
<div id="newCard" class="modal bottom-sheet"> 28 28 <div id="newCard" class="modal bottom-sheet">
<form id="new-card-form"> 29 29 <form id="new-card-form">
<div class="modal-content"> 30 30 <div class="modal-content">
<div class="input-field"> 31 31 <div class="input-field">
<!--<label id="newCardSign" for="newCard">New Flashcard Text</label>--> 32 32 <!--<label id="newCardSign" for="newCard">New Flashcard Text</label>-->
<div id="new-card-input" contenteditable style="outline:0px solid transparent;"> 33 33 <div class="feed-modal-input" id="new-card-input" contenteditable style="outline:0px solid transparent;">
34 34
</div> 35 35 </div>
</div> 36 36 </div>
</div> 37 37 </div>
<div class="modal-footer"> 38 38 <div class="modal-footer">
<button class="btn modal-close tooltipped" type="submit" ng-click="pushCard()" data-position="left" 39 39 <button class="btn modal-close tooltipped" type="submit" ng-click="pushCard()" data-position="left"
data-delay="50" 40 40 data-delay="50"
data-tooltip="Enter">Submit 41 41 data-tooltip="Enter">Submit
<i class="mdi-hardware-keyboard-return right"></i> 42 42 <i class="mdi-hardware-keyboard-return right"></i>
</button> 43 43 </button>
<button id="blank-selected" style="float:left" class="btn tooltipped" data-position="right" data-delay="50" 44 44 <button id="blank-selected" style="float:left" class="btn tooltipped" data-position="right" data-delay="50"