Compare View

switch
from
...
to
 
Commits (2)

Diff

Showing 5 changed files Inline Diff

angular.module('flashy', [ 1 1 angular.module('flashy', [
'flashy.LoginController', 2 2 'flashy.LoginController',
'flashy.RootController', 3 3 'flashy.RootController',
'flashy.FeedController', 4 4 'flashy.FeedController',
'flashy.DeckController', 5 5 'flashy.DeckController',
'flashy.ClassAddController', 6 6 'flashy.ClassAddController',
'flashy.RequestResetController', 7 7 'flashy.RequestResetController',
'flashy.StudyController', 8 8 'flashy.StudyController',
'flashy.UserService', 9 9 'flashy.UserService',
'flashy.FlashcardDirective', 10 10 'flashy.FlashcardDirective',
'flashy.FlashcardFactory', 11 11 'flashy.FlashcardFactory',
'flashy.ResetPasswordController', 12 12 'flashy.ResetPasswordController',
'flashy.VerifyEmailController', 13 13 'flashy.VerifyEmailController',
'flashy.CardListController', 14 14 'flashy.CardListController',
'flashy.HelpController', 15 15 'flashy.HelpController',
'flashy.SettingsController', 16 16 'flashy.SettingsController',
'ngCookies']). 17 17 'ngCookies']).
config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) { 18 18 config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) {
'use strict'; 19 19 'use strict';
$httpProvider.defaults.withCredentials = true; 20 20 $httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; 21 21 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 22 22 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$resourceProvider.defaults.stripTrailingSlashes = false; 23 23 $resourceProvider.defaults.stripTrailingSlashes = false;
var arrayMethods = Object.getOwnPropertyNames(Array.prototype); 24 24 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
arrayMethods.forEach(attachArrayMethodsToNodeList); 25 25 arrayMethods.forEach(attachArrayMethodsToNodeList);
function attachArrayMethodsToNodeList(methodName) { 26 26 function attachArrayMethodsToNodeList(methodName) {
if (methodName !== 'length') { 27 27 if (methodName !== 'length') {
NodeList.prototype[methodName] = Array.prototype[methodName]; 28 28 NodeList.prototype[methodName] = Array.prototype[methodName];
} 29 29 }
} 30 30 }
31 31
$httpProvider.interceptors.push(function($q, $rootScope) { 32 32 $httpProvider.interceptors.push(function($q, $rootScope) {
return { 33 33 return {
'responseError': function(rejection) { // need a better redirect 34 34 'responseError': function(rejection) { // need a better redirect
if (rejection.status >= 500) { 35 35 if (rejection.status >= 500) {
console.log('got error'); 36 36 console.log('got error');
console.log(rejection); 37 37 console.log(rejection);
$rootScope.$broadcast('server_error', rejection); 38 38 $rootScope.$broadcast('server_error', rejection);
} 39 39 }
if (rejection.status == 403) { 40 40 if (rejection.status == 403) {
console.log(rejection); 41 41 console.log(rejection);
if (rejection.data && rejection.data.detail == 'Please verify your email before continuing') { 42 42 if (rejection.data && rejection.data.detail == 'Please verify your email before continuing') {
UserService.showLockedMessage(); 43 43 UserService.showLockedMessage();
UserService.logout(); 44 44 UserService.logout();
} 45 45 }
} 46 46 }
if (rejection.status == 429) { 47 47 if (rejection.status == 429) {
console.log(rejection); 48 48 console.log(rejection);
Materialize.toast('Your enthusiasm is appreciated, but we ask that you slow down a little!', 4000); 49 49 Materialize.toast('Your enthusiasm is appreciated, but we ask that you slow down a little!', 4000);
} 50 50 }
return $q.reject(rejection); 51 51 return $q.reject(rejection);
} 52 52 }
}; 53 53 };
}); 54 54 });
$locationProvider.html5Mode(true); 55 55 $locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/404'); 56 56 $urlRouterProvider.otherwise('/login');
var auth_resolve = { 57 57 var auth_resolve = {
authorize: function($q, $rootScope, $state, $stateParams, UserService) { 58 58 authorize: function($q, $rootScope, $state, $stateParams, UserService) {
console.log('do we need to authorize a user for', $rootScope.nextState.name); 59 59 console.log('do we need to authorize a user for', $rootScope.nextState.name);
if (UserService.noAuthRequired($rootScope.nextState)) { 60 60 if (UserService.noAuthRequired($rootScope.nextState)) {
console.log('no auth required for', $rootScope.nextState.name); 61 61 console.log('no auth required for', $rootScope.nextState.name);
return UserService.getUserData(); 62 62 return UserService.getUserData();
} 63 63 }
console.log('resolving user before continuing to ' + $rootScope.nextState.name); 64 64 console.log('resolving user before continuing to ' + $rootScope.nextState.name);
var redirectAsNeeded = function() { 65 65 var redirectAsNeeded = function() {
if (!UserService.isLoggedIn()) { 66 66 if (!UserService.isLoggedIn()) {
console.log(UserService.getUserData()); 67 67 console.log(UserService.getUserData());
console.log('making the user log in'); 68 68 console.log('making the user log in');
$state.go('login'); 69 69 $state.go('login');
} 70 70 }
if (!UserService.authorizedFor($rootScope.nextState, $rootScope.nextStateParams)) { 71 71 if (!UserService.authorizedFor($rootScope.nextState, $rootScope.nextStateParams)) {
console.log('user not authorized for ' + $rootScope.nextState.name); 72 72 console.log('user not authorized for ' + $rootScope.nextState.name);
$state.go('addclass'); 73 73 $state.go('addclass');
} 74 74 }
}; 75 75 };
if (UserService.isResolved()) return redirectAsNeeded(); 76 76 if (UserService.isResolved()) return redirectAsNeeded();
return UserService.getUserData().then(redirectAsNeeded); 77 77 return UserService.getUserData().then(redirectAsNeeded);
} 78 78 }
}; 79 79 };
$stateProvider. 80 80 $stateProvider.
state('login', { 81 81 state('login', {
resolve: auth_resolve, 82 82 resolve: auth_resolve,
url: '/login', 83 83 url: '/login',
templateUrl: 'templates/login.html', 84 84 templateUrl: 'templates/login.html',
controller: 'LoginController' 85 85 controller: 'LoginController'
}). 86 86 }).
state('root', { 87 87 state('root', {
resolve: auth_resolve, 88 88 resolve: auth_resolve,
url: '/', 89 89 url: '',
controller: 'RootController' 90 90 controller: 'RootController'
}). 91 91 }).
state('feed', { 92 92 state('feed', {
resolve: auth_resolve, 93 93 resolve: auth_resolve,
url: '/feed/{sectionId}', 94 94 url: '/feed/{sectionId}',
templateUrl: 'templates/feed.html', 95 95 templateUrl: 'templates/feed.html',
controller: 'FeedController' 96 96 controller: 'FeedController'
}). 97 97 }).
state('cardlist', { 98 98 state('cardlist', {
resolve: auth_resolve, 99 99 resolve: auth_resolve,
url: '/cards/{sectionId}', 100 100 url: '/cards/{sectionId}',
templateUrl: 'templates/cardlist.html', 101 101 templateUrl: 'templates/cardlist.html',
controller: 'CardListController' 102 102 controller: 'CardListController'
}). 103 103 }).
state('addclass', { 104 104 state('addclass', {
resolve: auth_resolve, 105 105 resolve: auth_resolve,
url: '/addclass', 106 106 url: '/addclass',
templateUrl: 'templates/addclass.html', 107 107 templateUrl: 'templates/addclass.html',
controller: 'ClassAddController' 108 108 controller: 'ClassAddController'
}). 109 109 }).
state('deck', { 110 110 state('deck', {
resolve: auth_resolve, 111 111 resolve: auth_resolve,
url: '/deck/{sectionId}', 112 112 url: '/deck/{sectionId}',
templateUrl: 'templates/deck.html', 113 113 templateUrl: 'templates/deck.html',
controller: 'DeckController' 114 114 controller: 'DeckController'
}). 115 115 }).
state('study', { 116 116 state('study', {
resolve: auth_resolve, 117 117 resolve: auth_resolve,
url: '/study', 118 118 url: '/study',
templateUrl: 'templates/study.html', 119 119 templateUrl: 'templates/study.html',
controller: 'StudyController' 120 120 controller: 'StudyController'
}). 121 121 }).
/*state('flashcard', { 122 122 /*state('flashcard', {
resolve: auth_resolve, 123 123 resolve: auth_resolve,
url: '/flashcard', 124 124 url: '/flashcard',
templateUrl: 'templates/flashcard.html', 125 125 templateUrl: 'templates/flashcard.html',
controller: 'FlashcardController' 126 126 controller: 'FlashcardController'
}).*/ 127 127 }).*/
state('settings', { 128 128 state('settings', {
resolve: auth_resolve, 129 129 resolve: auth_resolve,
url: '/settings', 130 130 url: '/settings',
templateUrl: 'templates/settings.html', 131 131 templateUrl: 'templates/settings.html',
controller: 'SettingsController' 132 132 controller: 'SettingsController'
}). 133 133 }).
state('requestpasswordreset', { 134 134 state('requestpasswordreset', {
url: '/requestpasswordreset', 135 135 url: '/requestpasswordreset',
templateUrl: 'templates/requestpasswordreset.html', 136 136 templateUrl: 'templates/requestpasswordreset.html',
controller: 'RequestResetController' 137 137 controller: 'RequestResetController'
}). 138 138 }).
state('resetpassword', { 139 139 state('resetpassword', {
url: '/resetpassword/{uid}/{token}', 140 140 url: '/resetpassword/{uid}/{token}',
templateUrl: 'templates/resetpassword.html', 141 141 templateUrl: 'templates/resetpassword.html',
controller: 'ResetPasswordController' 142 142 controller: 'ResetPasswordController'
}). 143 143 }).
state('verifyemail', { 144 144 state('verifyemail', {
url: '/verifyemail/{key}', 145 145 url: '/verifyemail/{key}',
templateUrl: 'templates/verifyemail.html', 146 146 templateUrl: 'templates/verifyemail.html',
controller: 'VerifyEmailController' 147 147 controller: 'VerifyEmailController'
}). 148 148 }).
state('404', { 149 149 state('404', {
url: '/404', 150 150 url: '/404',
template: "<h1>This page doesn't exist!</h1>" 151 151 template: "<h1>This page doesn't exist!</h1>"
}). 152 152 }).
state('help', { 153 153 state('help', {
resolve: auth_resolve, 154 154 resolve: auth_resolve,
url: '/help', 155 155 url: '/help',
templateUrl: 'templates/help.html', 156 156 templateUrl: 'templates/help.html',
controller: 'HelpController' 157 157 controller: 'HelpController'
}); 158 158 });
}). 159 159 }).
run(function($rootScope, $state, $stateParams, $location, UserService) { 160 160 run(function($rootScope, $state, $stateParams, $location, UserService) {
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { 161 161 $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
console.log('failed to change state: ' + error); 162 162 console.log('failed to change state: ' + error);
$state.go('login'); 163 163 $state.go('login');
}); 164 164 });
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { 165 165 $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$rootScope.nextState = toState; 166 166 $rootScope.nextState = toState;
$rootScope.nextStateParams = toParams; 167 167 $rootScope.nextStateParams = toParams;
console.log('changing state to', toState); 168 168 console.log('changing state to', toState);
if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) { 169 169 if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) {
localStorage.setItem('last_state', toState.name); 170 170 localStorage.setItem('last_state', toState.name);
localStorage.setItem('last_state_params', JSON.stringify(toParams)); 171 171 localStorage.setItem('last_state_params', JSON.stringify(toParams));
} 172 172 }
}); 173 173 });
}); 174 174 });
175 175
scripts/DeckController.js View file @ 30f54ec
angular.module('flashy.DeckController', ['ui.router', 'ngWebSocket']). 1 1 angular.module('flashy.DeckController', ['ui.router', 'ngWebSocket']).
2 2
controller('DeckController', 3 3 controller('DeckController',
function($scope, $rootScope, $state, $http, $window, $timeout, $stateParams, $websocket, $interval, UserService, Flashcard, Deck) { 4 4 function($scope, $rootScope, $state, $http, $window, $timeout, $stateParams, $websocket, $interval, UserService, Flashcard, Deck) {
angular.module('flashy.CardGridController').CardGridController.apply(this, arguments).then(function() { 5 5 angular.module('flashy.CardGridController').CardGridController.apply(this, arguments).then(function() {
$scope.refreshLayout(); 6 6 $scope.refreshLayout();
}); 7 7 });
$scope.cards = $scope.deck.cards; 8 8 $scope.cards = $scope.deck.cards;
$scope.deckPullCallback = $scope.addCardToGrid; 9 9 $scope.deckPullCallback = $scope.addCardToGrid;
$scope.deckUnpullCallback = $scope.hideCardFromGrid; 10 10 $scope.deckUnpullCallback = $scope.hideCardFromGrid;
11
12
13
14 $scope.refreshEditCardInput = function () {
15
16
17 console.log("CARD IS BEING EDITED");
18
19 $scope.editCardText = $('#edit-card-input').text();
20
21 $scope.submit_enabled = $scope.editCardText.length >= 5 && $scope.editCardText.length <= 160;
22
23
24
25 var i = 0;
26 $scope.editCardBlanks = [];
27 $('#edit-card-input')[0].childNodes.forEach(function (node) {
28 node = $(node)[0];
29 if (node.tagName == 'B') {
30 var text = $(node).text();
31 var leftspaces = 0, rightspaces = 0;
32 // awful way to find the first non-space character from the left or the right. thanks.js
33 while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++;
34 while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++;
35 console.log(leftspaces, text.length);
36 if (leftspaces != text.length) $scope.editCardBlanks.push([i + leftspaces, i + text.length - rightspaces]);
37 i += text.length;
38 } else if (!node.data) {
39 i += $(node).text().length;
40 } else {
41 i += node.data.length;
42 }
43 });
44 $scope.editCardBlanks.sort(function (a, b) {
45 return a[0] - b[0];
46 });
47 i = 0;
48 newtext = '';
49 $scope.editCardBlanks.forEach(function (blank) {
50 newtext += $scope.editCardText.slice(i, blank[0]);
51 newtext += '<b>' + $scope.editCardText.slice(blank[0], blank[1]) + '</b>';
52 i = blank[1];
53 });
54 newtext += $scope.editCardText.slice(i);
55 //$scope.newCardFormattedText = newtext;
56
57
58 };
59
60
61
62 $scope.saveChanges = function () {
63
64
65 var myCard = {
66 'text': $('#edit-card-input').text(),
67 'mask': $scope.editCardBlanks,
68 };
69
70 //console.log($scope.Flashcard.id);
71
72 if (myCard.text == '') {
73 console.log('blank flashcard not pushed:' + myCard.text);
74 //return closeNewCard();
75
76 $('#editModal').closeModal();
77
78 }
79 $http.patch('/api/flashcards/' + $scope.Flashcard.id, myCard).
80 success(function (data) {
81 console.log('flashcard pushed: ' + myCard.text);
82 if (!UserService.hasVerifiedEmail()) {
83 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
84 }
85 });
86
87 $('#editModal').closeModal();
88
89 }
90
91
92
93
94 $scope.discardChanges = function() {
95
96 $('#editModal').closeModal();
97
98 }
99
11 100 }
12 101 );
13 102
14
15
$scope.refreshEditCardInput = function () { 16
17
18
console.log("CARD IS BEING EDITED"); 19
20
$scope.editCardText = $('#edit-card-input').text(); 21
22
$scope.submit_enabled = $scope.editCardText.length >= 5 && $scope.editCardText.length <= 160; 23
24
25
26
var i = 0; 27
$scope.editCardBlanks = []; 28
$('#edit-card-input')[0].childNodes.forEach(function (node) { 29
node = $(node)[0]; 30
if (node.tagName == 'B') { 31
var text = $(node).text(); 32
var leftspaces = 0, rightspaces = 0; 33
// awful way to find the first non-space character from the left or the right. thanks.js 34
while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++; 35
while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++; 36
console.log(leftspaces, text.length); 37
if (leftspaces != text.length) $scope.editCardBlanks.push([i + leftspaces, i + text.length - rightspaces]); 38
i += text.length; 39
} else if (!node.data) { 40
i += $(node).text().length; 41
} else { 42
i += node.data.length; 43
} 44
}); 45
$scope.editCardBlanks.sort(function (a, b) { 46
return a[0] - b[0]; 47
}); 48
i = 0; 49
newtext = ''; 50
$scope.editCardBlanks.forEach(function (blank) { 51
newtext += $scope.editCardText.slice(i, blank[0]); 52
newtext += '<b>' + $scope.editCardText.slice(blank[0], blank[1]) + '</b>'; 53
i = blank[1]; 54
}); 55
newtext += $scope.editCardText.slice(i); 56
//$scope.newCardFormattedText = newtext; 57
58
59
}; 60
61
62
63
$scope.saveChanges = function () { 64
65
66
var myCard = { 67
'text': $('#edit-card-input').text(), 68
'mask': $scope.editCardBlanks, 69
}; 70
scripts/FlashcardFactory.js View file @ 30f54ec
angular.module('flashy.FlashcardFactory', ['ui.router']). 1 1 angular.module('flashy.FlashcardFactory', ['ui.router']).
factory('Flashcard', function ($http, UserService) { 2 2 factory('Flashcard', function ($http, UserService) {
var FlashcardCache = []; 3 3 var FlashcardCache = [];
var Deck = null; 4 4 var Deck = null;
var Flashcard = function (data) { 5 5 var Flashcard = function (data) {
if (typeof data == 'number') return FlashcardCache[data]; 6 6 if (typeof data == 'number') return FlashcardCache[data];
if (FlashcardCache[data.id]) return FlashcardCache[data.id]; 7 7 if (FlashcardCache[data.id]) return FlashcardCache[data.id];
for (var k in data) this[k] = data[k]; 8 8 for (var k in data) this[k] = data[k];
this.textPieces = []; 9 9 this.textPieces = [];
this.mask.sort(function (a, b) { 10 10 this.mask.sort(function (a, b) {
return a[0] - b[0]; 11 11 return a[0] - b[0];
}); 12 12 });
var i = 0; 13 13 var i = 0;
this.mask.forEach(function (blank) { 14 14 this.mask.forEach(function (blank) {
this.textPieces.push({text: this.text.slice(i, blank[0])}); 15 15 this.textPieces.push({text: this.text.slice(i, blank[0])});
this.textPieces.push({text: this.text.slice(blank[0], blank[1]), blank: true}); 16 16 this.textPieces.push({text: this.text.slice(blank[0], blank[1]), blank: true});
i = blank[1]; 17 17 i = blank[1];
}, this); 18 18 }, this);
this.textPieces.push({text: this.text.slice(i)}); 19 19 this.textPieces.push({text: this.text.slice(i)});
this.formatted_text = ''; 20 20 this.formatted_text = '';
for (i in this.textPieces) { 21 21 for (i in this.textPieces) {
p = this.textPieces[i]; 22 22 p = this.textPieces[i];
this.formatted_text += p.blank ? '<b>' + p.text + '</b>' : p.text; 23 23 this.formatted_text += p.blank ? '<b>' + p.text + '</b>' : p.text;
} 24 24 }
this.moveUp = false; 25 25 this.moveUp = false;
this.moveDown = false; 26 26 this.moveDown = false;
this.colNum = 0; 27 27 this.colNum = 0;
this.colRank = 0; 28 28 this.colRank = 0;
FlashcardCache[this.id] = this; 29 29 FlashcardCache[this.id] = this;
}; 30 30 };
31 31
Flashcard.prototype.isInDeck = function () { 32 32 Flashcard.prototype.isInDeck = function () {
return !(typeof Deck.contains(this.id) === 'undefined'); 33 33 return !(typeof Deck.contains(this.id) === 'undefined');
}; 34 34 };
Flashcard.prototype.pullUnpull = function () { 35 35 Flashcard.prototype.pullUnpull = function () {
if (this.isInDeck()) this.unpull(); 36 36 if (this.isInDeck()) this.unpull();
else this.pull(); 37 37 else this.pull();
}; 38 38 };
Flashcard.prototype.pull = function () { 39 39 Flashcard.prototype.pull = function () {
if (this.isInDeck()) return console.log('Not pulling', this.id, "because it's already in deck"); 40 40 if (this.isInDeck()) return console.log('Not pulling', this.id, "because it's already in deck");
return $http.post('/api/flashcards/' + this.id + '/pull/'); 41 41 return $http.post('/api/flashcards/' + this.id + '/pull/');
}; 42 42 };
Flashcard.prototype.unpull = function () { 43 43 Flashcard.prototype.unpull = function () {
if (!this.isInDeck()) return console.log('Not unpulling', this.id, "because it's not in deck"); 44 44 if (!this.isInDeck()) return console.log('Not unpulling', this.id, "because it's not in deck");
return $http.post('/api/flashcards/' + this.id + '/unpull/'); 45 45 return $http.post('/api/flashcards/' + this.id + '/unpull/');
}; 46 46 };
Flashcard.prototype.hide = function () { 47 47 Flashcard.prototype.hide = function () {
return $http.post('/api/flashcards/' + this.id + '/hide/'); 48 48 return $http.post('/api/flashcards/' + this.id + '/hide/');
}; 49 49 };
Flashcard.prototype.unhide = function () { 50 50 Flashcard.prototype.unhide = function () {
return $http.post('/api/flashcards/' + this.id + '/unhide/'); 51 51 return $http.post('/api/flashcards/' + this.id + '/unhide/');
}; 52 52 };
Flashcard.cleanup = function () { 53 53 Flashcard.cleanup = function () {
Deck = null; 54 54 Deck = null;
FlashcardCache = []; 55 55 FlashcardCache = [];
}; 56 56 };
Flashcard.linkDeck = function(deck){ 57 57 Flashcard.linkDeck = function(deck){
Deck = deck; 58 58 Deck = deck;
} 59 59 }
60 60
Flashcard.prototype.edit = function () { 61 61 Flashcard.prototype.edit = function () {
62 62
63 63
var editableText = this.formatted_text; 64 64 var editableText = this.formatted_text;
65 65
$('.modal-trigger').leanModal({ 66 66 $('.modal-trigger').leanModal({
dismissible: true, // Modal can be dismissed by clicking outside of the modal 67 67 dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: .5, // Opacity of modal background 68 68 opacity: .5, // Opacity of modal background
in_duration: 300, // Transition in duration 69 69 in_duration: 300, // Transition in duration
out_duration: 200, // Transition out duration 70 70 out_duration: 200, // Transition out duration
ready: function () { 71 71 ready: function () {
72 72
$('#edit-card-input').html(editableText); 73 73 $('#edit-card-input').html(editableText);
74 74
75 75
}, // Callback for Modal open 76 76 }, // Callback for Modal open
complete: function () { 77 77 complete: function () {
78 78
console.log("EDIT MODAL CLOSED"); 79 79 console.log("EDIT MODAL CLOSED");
templates/deck.html View file @ 30f54ec
<!-- Edit Modal --> 1 1 <!-- Edit Modal -->
<div id="editModal" class="modal row" style="max-height:none;"> 2 2 <div id="editModal" class="modal row" style="max-height:none;">
<form id="edit-card-form"> 3 3 <form id="edit-card-form">
<div class="modal-content col"> 4 4 <div class="modal-content col">
<div class="row" style="margin-bottom:0"> 5 5 <div class="row" style="margin-bottom:0">
<div class="card cyan-text text-darken-2" 6 6 <div class="card cyan-text text-darken-2"
style="width:300px; height:180px; margin-bottom:0; font-size:120%;"> 7 7 style="width:300px; height:180px; margin-bottom:0; font-size:120%;">
<div class="valign-wrapper"> 8 8 <div class="valign-wrapper">
<div id="edit-card-input" ng-model="newCardFormattedText" style="outline:0px solid transparent;" 9 9 <div id="edit-card-input" ng-model="newCardFormattedText" style="outline:0px solid transparent;"
class="card-content valign center-align" 10 10 class="card-content valign center-align"
11 contenteditable select-non-editable="true" ng-change="refreshEditCardInput()">
12 </div>
contenteditable select-non-editable="true" ng-change="refreshEditCardInput()"> 11 13 </div>
</div> 12 14 </div>
</div> 13 15 </div>
</div> 14 16 </div>
</div> 15 17 <div class="col">
</div> 16 18 <div class="row">
<div class="col"> 17 19 </div>
<div class="row"> 18 20 <div class="row">
</div> 19 21 <button class="btn modal-close" type="submit" ng-click="saveChanges()"
<div class="row"> 20 22 data-position="left"
<button class="btn modal-close" type="submit" ng-click="saveChanges()" 21 23 data-delay="50" ng-class="submit_enabled?{}:'disabled'">
data-position="left" 22 24 Save Changes
data-delay="50" ng-class="submit_enabled?{}:'disabled'"> 23 25 <i class="mdi-action-done right"></i>
Save Changes 24 26 </button>
<i class="mdi-action-done right"></i> 25 27 </div>
</button> 26 28
</div> 27 29
28 30 <div class="row">
29 31 <button class="btn modal-close red" ng-click="discardChanges()"
<div class="row"> 30 32 data-position="left"
<button class="btn modal-close red" ng-click="discardChanges()" 31 33 data-delay="50">
data-position="left" 32 34 Discard Changes
data-delay="50"> 33 35 <i class="mdi-content-clear right"></i>
Discard Changes 34 36 </button>
<i class="mdi-content-clear right"></i> 35 37 </div>
</button> 36 38
</div> 37 39 <div class="row">
38 40 <button id="blank-selected" style="float:left" class="btn" data-position="right" data-delay="50">
<div class="row"> 39 41 Blank Selected Text
<button id="blank-selected" style="float:left" class="btn" data-position="right" data-delay="50"> 40 42 </button>
Blank Selected Text 41 43 </div>
</button> 42 44
</div> 43 45
46 <div class="row" ng-show="editCardText" ng-style="(editCardText.length>160)?{color:'red'}:{}">
47 {{editCardText.length}}/160 characters
48 </div>
49 <div class="row" ng-show="editCardText.length < 5">
50 Please write a little more!
51 </div>
52 <div class="row" ng-show="editCardText.length > 140">
53 Good flashcards have a<br>
54 single atomic fact
55 </div>
44 56 </div>
45 57 </form>
<div class="row" ng-show="editCardText" ng-style="(editCardText.length>160)?{color:'red'}:{}"> 46 58 </div>
{{editCardText.length}}/160 characters 47 59
60
61
62
63
</div> 48 64
<div class="row" ng-show="editCardText.length < 5"> 49 65 <div class="row">
Please write a little more! 50 66 <h2 class="weight" ng-cloak ng-show="cardCols && cards.length == 0">Your deck is empty.</h2>
</div> 51 67 <h2 class="weight" ng-cloak ng-show="cardCols && cards.length == 0">Add a card from the feed to see it here.</h2>
<div class="row" ng-show="editCardText.length > 140"> 52 68
Good flashcards have a<br> 53 69 <div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="!cardCols">
single atomic fact 54 70 <div class="indeterminate"></div>
</div> 55 71 </div>
</div> 56 72
</form> 57 73 <div class="cardColumn" ng-repeat="col in cardCols">
</div> 58 74 <div class="repeated-card" ng-repeat="card in col">
59 75 <flashcard flashcard-obj="card"/>
60 76 </div>
61 77 </div>
62 78 </div>
63
64
<div class="row"> 65
<h2 ng-cloak ng-show="cards.length == 0">This is your deck, but it's blank! Add a card from the feed to see it 66
here!</h2> 67
68
<div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="cards === false"> 69
<div class="indeterminate"></div> 70
</div> 71
72
<div class="cardColumn" ng-repeat="col in cardCols"> 73
<div class="repeated-card" ng-repeat="card in col"> 74
<flashcard flashcard-obj="card"/> 75
</div> 76
</div> 77
</div> 78
templates/flashcard.html View file @ 30f54ec
<div class="card flashy smallify black-text text-darken-2" 1 1 <div class="card flashy smallify black-text text-darken-2"
ng-class="{'in-deck':flashcard.isInDeck(), 'card-moveUp':flashcard.moveUp, 2 2 ng-class="{'in-deck':flashcard.isInDeck(), 'card-moveUp':flashcard.moveUp,
'card-moveDown':flashcard.moveDown}"> 3 3 'card-moveDown':flashcard.moveDown}">
<div class="valign-wrapper"> 4 4 <div class="valign-wrapper">
<div class="card-content valign center-align" ng-bind-html="flashcard.formatted_text"></div> 5 5 <div class="card-content valign center-align" ng-bind-html="flashcard.formatted_text"></div>
</div> 6 6 </div>
7 7
8 8
<div class="card-overlay"> 9 9 <div class="card-overlay">
<div class="top-box no-user-select" 10 10 <div class="top-box no-user-select"
ng-click="flashcard.pullUnpull()"> 11 11 ng-click="flashcard.pullUnpull()">
<div class="center-me"> 12 12 <div class="center-me">
<i ng-if="flashcard.isInDeck()" class="fadey mdi-content-remove-circle-outline medium"></i> 13 13 <i ng-if="flashcard.isInDeck()" class="fadey mdi-content-remove-circle-outline medium"></i>
<i ng-if="!flashcard.isInDeck()" class="fadey mdi-content-add-circle-outline medium"></i> 14 14 <i ng-if="!flashcard.isInDeck()" class="fadey mdi-content-add-circle-outline medium"></i>
</div> 15 15 </div>
</div> 16 16 </div>
<div class="bottom-box no-user-select"> 17 17 <div class="bottom-box no-user-select">
18 18
<div class="left-box"> 19 19 <div class="left-box">
<div class="center-me modal-trigger" href="#editModal" ng-click="flashcard.edit()"><i class="mdi-editor-border-color small"></i></div> 20 20 <div class="center-me modal-trigger" href="#editModal" ng-click="flashcard.edit()"><i class="mdi-editor-border-color small"></i></div>
</div> 21 21 </div>
22 22
<div class="right-box" ng-click="flashcard.hide()"> 23 23 <div class="right-box" ng-click="flashcard.hide()">
<div class="center-me"><i class="mdi-action-delete small"></i></div> 24 24 <div class="center-me"><i class="mdi-action-visibility-off small"></i></div>
</div> 25 25 </div>
26 26
</div> 27 27 </div>
</div> 28 28 </div>
29 29
30 30
31
32