Compare View

switch
from
...
to
 
Commits (3)

Diff

Showing 4 changed files Inline Diff

scripts/FeedController.js View file @ 0c0dbdc
File was created 1 angular.module('flashy.FeedController',
2 ['ui.router',
3 'ngAnimate',
4 'ngWebSocket',
5 'contenteditable',
6 'flashy.DeckFactory']).controller('FeedController',
7 function($scope, $rootScope, $state, $http, $window, $timeout, $stateParams, $websocket, $interval, UserService, Flashcard, Deck) {
8 angular.module('flashy.CardGridController').CardGridController.apply(this, arguments);
9 var promise;
10 $rootScope.debugFlashcard = false;
11
12 $scope.updateCardScore = function(card, scoreChange) {
13 console.log('update card score');
14 // if no colNum is attached, then this doesn't exist on the feed yet
15 if (!card.colNum) return;
16 /*$scope.cardCols[card.colNum].sort(function(a, b) {
17 return b.score - a.score;
18 });*/
19
20 card.score += scoreChange;
21 var col = card.colNum;
22 var rank = card.colRank;
23 var s = Math.sign(scoreChange);
24
25 rank -= s;
26 if (rank < 0) return;
27 if (rank == $scope.cardCols[col].length) return;
28
29 $scope.affectedCards = [];
30 while (s * $scope.cardCols[col][rank].score < s * card.score) {
31 $scope.affectedCards.push($scope.cardCols[col][rank]);
32 rank -= s;
33 if (rank < 0) break;
34 if (rank == $scope.cardCols[col].length) break;
35 }
36
37 /*var direction = s ? 'margin-
38 var computedStyle = $boxTwo.css('margin-left');
39 $boxTwo.removeClass('horizTranslate');
40 $boxTwo.css('margin-left', computedStyle);*/
41
42 $scope.cardCols[col].splice(rank + s, 0, $scope.cardCols[col].splice(card.colRank, 1)[0]);
43 $scope.updateColRanks($scope.cardCols[card.colNum]); // can be optimized out
44 };
45
46
47
48 $scope.feed_ws = $websocket($scope.ws_host + '/ws/feed/' + $scope.sectionId + '?subscribe-broadcast');
49 $scope.feed_ws.onMessage(function (e) {
50
51
52 console.log("oh yeaaaaaaaaaaaaaaaaaaa");
53
54 data = JSON.parse(e.data);
55 console.log('message', data);
56 if (data.event_type == 'new_card') {
57 $scope.addCardToGrid(new Flashcard(data.flashcard, $scope.deck));
58 } else if (data.event_type == 'score_change') {
59 card = new Flashcard(data.flashcard); // doesnt create a card if it exists
60 console.log('score change');
61 $scope.updateCardScore(card, data.flashcard.score - card.score);
62 }
63 });
64
65 $scope.pushCard = function() {
66 var myCard = {
67 // we can't trim this string because it'd mess up the blanks. Something to fix.
68 'text': $('#new-card-input').text(),
69 'mask': $scope.newCardBlanks,
70 section: $scope.section.id
71 };
72 if (myCard.text == '') {
73 console.log('blank flashcard not pushed:' + myCard.text);
74 return closeNewCard();
75 }
76 $http.post('/api/flashcards/', myCard).
77 success(function(data) {
78 console.log('flashcard pushed: ' + myCard.text);
79 if (!UserService.hasVerifiedEmail()) {
80 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
81 }
82 });
83 return $scope.closeNewCardModal();
84 };
85
86 /* Key bindings for the whole feed window. Hotkey it up! */
87 var listenForC = true;
88
89 // Need to pass these options into openmodal and leanmodal,
90 // otherwise the ready handler doesn't get called
91
92 modal_options = {
93 dismissible: true, // Modal can be dismissed by clicking outside of the modal
94 opacity: 0, // Opacity of modal background
95 in_duration: 300, // Transition in duration
96 out_duration: 200, // Transition out duration
97 ready: function() {
98 $('#new-card-input').focus();
99 document.execCommand('selectAll', false, null);
100 }
101 };
102
103 $(document).keydown(function(e) {
104 var keyed = e.which;
105 if (keyed == 67 && listenForC) { // "c" for compose
106 $scope.openNewCardModal();
107 e.preventDefault();
108 return false;
109 } else if (keyed == 27) { // clear on ESC
110 $scope.closeNewCardModal();
111 }
112 });
113
114 $scope.openNewCardModal = function() {
115 $('#newCard').openModal(modal_options);
116 listenForC = false;
117 $('#new-card-input').html('Write a flashcard!');
118 };
119
120 $scope.closeNewCardModal = function() {
121 listenForC = true;
122 $('#new-card-input').html('').blur();
123 $('#newCard').closeModal(modal_options);
124 };
125
126 $('.tooltipped').tooltip({delay: 50});
127 // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
128 $('.modal-trigger').leanModal(modal_options);
129 $('#new-card-input').on('keydown', function(e) {
130 if (e.which == 13) {
131 e.preventDefault();
132 if ($scope.submit_enabled) {
133 $scope.pushCard();
134 listenForC = true;
135 }
136 return false;
137 } else {
138
139 }
140 });
141 $('button#blank-selected').click(function() {
142 console.log(window.getSelection());
143 document.execCommand('bold');
144 });
145 $scope.newCardBlanks = [];
146 $scope.refreshNewCardInput = function() {
147 $scope.newCardText = $('#new-card-input').text();
148 $scope.submit_enabled = $scope.newCardText.length >= 5 && $scope.newCardText.length <= 160;
149 var i = 0;
150 $scope.newCardBlanks = [];
151 $('#new-card-input')[0].childNodes.forEach(function(node) {
152 node = $(node)[0];
153 if (node.tagName == 'B') {
154 var text = $(node).text();
155 var leftspaces = 0, rightspaces = 0;
156 // awful way to find the first non-space character from the left or the right. thanks.js
157 while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++;
158 while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++;
159 console.log(leftspaces, text.length);
160 if (leftspaces != text.length) $scope.newCardBlanks.push([i + leftspaces, i + text.length - rightspaces]);
161 i += text.length;
162 } else if (!node.data) {
163 i += $(node).text().length;
164 } else {
165 i += node.data.length;
166 }
167 });
168 $scope.newCardBlanks.sort(function(a, b) {
169 return a[0] - b[0];
170 });
171 i = 0;
172 newtext = '';
173 $scope.newCardBlanks.forEach(function(blank) {
174 newtext += $scope.newCardText.slice(i, blank[0]);
175 newtext += '<b>' + $scope.newCardText.slice(blank[0], blank[1]) + '</b>';
176 i = blank[1];
177 });
178 newtext += $scope.newCardText.slice(i);
179 //$scope.newCardFormattedText = newtext;
180 };
181 $scope.shuffleCards = function() {
182 $timeout(function() {
183 (function(o) {
184 for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
185 return o;
186 })($scope.cardCols[0]);
187 });
188 };
189 $scope.$on('$destroy', function() {
190 $scope.feed_ws.close();
191 $interval.cancel(promise);
192 });
193 return $http.get('/api/sections/' + sectionId + '/feed/').
194 success(function(data) {
195 console.log(data);
196 $scope.cards = data.map(function(card) {
197 return new Flashcard(card, $scope.deck);
198 });
199 $scope.refreshLayout().then(function() {
200 $timeout($scope.refreshColumnWidth).then(function() {
201 $scope.showGrid = true;
202 });
203 console.log('layout done');
204 });
205 });
206
207
208 });
angular.module('flashy.FeedController', 1
['ui.router', 2
'ngAnimate', 3
'ngWebSocket', 4
'contenteditable', 5
'flashy.DeckFactory']).controller('FeedController', 6
function($scope, $rootScope, $state, $http, $window, $timeout, $stateParams, $websocket, $interval, UserService, Flashcard, Deck) { 7
angular.module('flashy.CardGridController').CardGridController.apply(this, arguments); 8
var promise; 9
$rootScope.debugFlashcard = false; 10
11
$scope.updateCardScore = function(card, scoreChange) { 12
console.log('update card score'); 13
// if no colNum is attached, then this doesn't exist on the feed yet 14
if (!card.colNum) return; 15
/*$scope.cardCols[card.colNum].sort(function(a, b) { 16
return b.score - a.score; 17
});*/ 18
19
card.score += scoreChange; 20
var col = card.colNum; 21
var rank = card.colRank; 22
var s = Math.sign(scoreChange); 23
24
rank -= s; 25
if (rank < 0) return; 26
if (rank == $scope.cardCols[col].length) return; 27
28
$scope.affectedCards = []; 29
while (s * $scope.cardCols[col][rank].score < s * card.score) { 30
$scope.affectedCards.push($scope.cardCols[col][rank]); 31
rank -= s; 32
if (rank < 0) break; 33
if (rank == $scope.cardCols[col].length) break; 34
} 35
36
/*var direction = s ? 'margin- 37
var computedStyle = $boxTwo.css('margin-left'); 38
$boxTwo.removeClass('horizTranslate'); 39
$boxTwo.css('margin-left', computedStyle);*/ 40
41
$scope.cardCols[col].splice(rank + s, 0, $scope.cardCols[col].splice(card.colRank, 1)[0]); 42
$scope.updateColRanks($scope.cardCols[card.colNum]); // can be optimized out 43
}; 44
45
46
47
$scope.feed_ws = $websocket($scope.ws_host + '/ws/feed/' + $scope.sectionId + '?subscribe-broadcast'); 48
$scope.feed_ws.onMessage(function (e) { 49
50
51
console.log("oh yeaaaaaaaaaaaaaaaaaaa"); 52
53
data = JSON.parse(e.data); 54
console.log('message', data); 55
if (data.event_type == 'new_card') { 56
$scope.addCardToGrid(new Flashcard(data.flashcard, $scope.deck)); 57
} else if (data.event_type == 'score_change') { 58
card = new Flashcard(data.flashcard); // doesnt create a card if it exists 59
console.log('score change'); 60
$scope.updateCardScore(card, data.flashcard.score - card.score); 61
} 62
}); 63
64
$scope.pushCard = function() { 65
var myCard = { 66
// we can't trim this string because it'd mess up the blanks. Something to fix. 67
'text': $('#new-card-input').text(), 68
'mask': $scope.newCardBlanks, 69
section: $scope.section.id 70
}; 71
if (myCard.text == '') { 72
console.log('blank flashcard not pushed:' + myCard.text); 73
return closeNewCard(); 74
} 75
$http.post('/api/flashcards/', myCard). 76
success(function(data) { 77
console.log('flashcard pushed: ' + myCard.text); 78
if (!UserService.hasVerifiedEmail()) { 79
Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000); 80
} 81
}); 82
return $scope.closeNewCardModal(); 83
}; 84
85
/* Key bindings for the whole feed window. Hotkey it up! */ 86
var listenForC = true; 87
88
// Need to pass these options into openmodal and leanmodal, 89
// otherwise the ready handler doesn't get called 90
91
modal_options = { 92
dismissible: true, // Modal can be dismissed by clicking outside of the modal 93
opacity: 0, // Opacity of modal background 94
in_duration: 300, // Transition in duration 95
out_duration: 200, // Transition out duration 96
ready: function() { 97
$('#new-card-input').focus(); 98
document.execCommand('selectAll', false, null); 99
} 100
}; 101
102
$(document).keydown(function(e) { 103
var keyed = e.which; 104
if (keyed == 67 && listenForC) { // "c" for compose 105
$scope.openNewCardModal(); 106
e.preventDefault(); 107
return false; 108
} else if (keyed == 27) { // clear on ESC 109
$scope.closeNewCardModal(); 110
} 111
}); 112
113
$scope.openNewCardModal = function() { 114
$('#newCard').openModal(modal_options); 115
listenForC = false; 116
$('#new-card-input').html('Write a flashcard!'); 117
}; 118
119
$scope.closeNewCardModal = function() { 120
listenForC = true; 121
$('#new-card-input').html('').blur(); 122
$('#newCard').closeModal(modal_options); 123
}; 124
125
$('.tooltipped').tooltip({delay: 50}); 126
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered 127
$('.modal-trigger').leanModal(modal_options); 128
$('#new-card-input').on('keydown', function(e) { 129
if (e.which == 13) { 130
e.preventDefault(); 131
if ($scope.submit_enabled) { 132
$scope.pushCard(); 133
listenForC = true; 134
} 135
return false; 136
} else { 137
138
} 139
}); 140
$('button#blank-selected').click(function() { 141
console.log(window.getSelection()); 142
document.execCommand('bold'); 143
}); 144
$scope.newCardBlanks = []; 145
$scope.refreshNewCardInput = function() { 146
$scope.newCardText = $('#new-card-input').text(); 147
$scope.submit_enabled = $scope.newCardText.length >= 5 && $scope.newCardText.length <= 160; 148
var i = 0; 149
$scope.newCardBlanks = []; 150
$('#new-card-input')[0].childNodes.forEach(function(node) { 151
node = $(node)[0]; 152
if (node.tagName == 'B') { 153
var text = $(node).text(); 154
var leftspaces = 0, rightspaces = 0; 155
// awful way to find the first non-space character from the left or the right. thanks.js 156
while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++; 157
while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++; 158
console.log(leftspaces, text.length); 159
if (leftspaces != text.length) $scope.newCardBlanks.push([i + leftspaces, i + text.length - rightspaces]); 160
i += text.length; 161
} else if (!node.data) { 162
i += $(node).text().length; 163
} else { 164
i += node.data.length; 165
} 166
}); 167
$scope.newCardBlanks.sort(function(a, b) { 168
return a[0] - b[0]; 169
}); 170
i = 0; 171
newtext = ''; 172
$scope.newCardBlanks.forEach(function(blank) { 173
newtext += $scope.newCardText.slice(i, blank[0]); 174
newtext += '<b>' + $scope.newCardText.slice(blank[0], blank[1]) + '</b>'; 175
i = blank[1]; 176
}); 177
newtext += $scope.newCardText.slice(i); 178
//$scope.newCardFormattedText = newtext; 179
}; 180
$scope.shuffleCards = function() { 181
$timeout(function() { 182
(function(o) { 183
for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); 184
return o; 185
scripts/FlashcardDirective.js View file @ 0c0dbdc
angular.module('flashy.FlashcardDirective', []). 1 1 angular.module('flashy.FlashcardDirective', []).
2 2
directive('flashcard', 3 3 directive('flashcard',
4 4
5
6 function($http, $state, $window) {
5 7 return {
function($http, $state, $window) { 6 8 templateUrl: '/app/templates/flashcard.html',
return { 7 9 restrict: 'E',
templateUrl: '/app/templates/flashcard.html', 8 10 scope: {
restrict: 'E', 9 11 flashcard: '=flashcardObj', // flashcard-obj in parent html
scope: { 10 12 refresh: '&' // eval refresh in parent html
flashcard: '=flashcardObj', // flashcard-obj in parent html 11 13 },
refresh: '&' // eval refresh in parent html 12 14 colNum: 0,
}, 13 15 colRank: 0,
colNum: 0, 14 16 link: function(scope, element) {
colRank: 0, 15 17 $('.tooltipped').tooltip();
link: function(scope, element) { 16 18 // /* Handles width of the card */
$('.tooltipped').tooltip(); 17 19 }
// /* Handles width of the card */ 18 20 };
} 19 21 }
22
}; 20 23 );
} 21
22 24
25
); 23
24
25
scripts/FlashcardFactory.js View file @ 0c0dbdc
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 }
FlashcardCache[this.id] = this; 25 25 FlashcardCache[this.id] = this;
}; 26 26 };
27 27
Flashcard.prototype.isInDeck = function () { 28 28 Flashcard.prototype.isInDeck = function () {
return !(typeof Deck.contains(this.id) === 'undefined'); 29 29 return !(typeof Deck.contains(this.id) === 'undefined');
}; 30 30 };
Flashcard.prototype.pullUnpull = function () { 31 31 Flashcard.prototype.pullUnpull = function () {
if (this.isInDeck()) this.unpull(); 32 32 if (this.isInDeck()) this.unpull();
else this.pull(); 33 33 else this.pull();
}; 34 34 };
Flashcard.prototype.pull = function () { 35 35 Flashcard.prototype.pull = function () {
if (this.isInDeck()) return console.log('Not pulling', this.id, "because it's already in deck"); 36 36 if (this.isInDeck()) return console.log('Not pulling', this.id, "because it's already in deck");
return $http.post('/api/flashcards/' + this.id + '/pull/'); 37 37 return $http.post('/api/flashcards/' + this.id + '/pull/');
}; 38 38 };
Flashcard.prototype.unpull = function () { 39 39 Flashcard.prototype.unpull = function () {
if (!this.isInDeck()) return console.log('Not unpulling', this.id, "because it's not in deck"); 40 40 if (!this.isInDeck()) return console.log('Not unpulling', this.id, "because it's not in deck");
return $http.post('/api/flashcards/' + this.id + '/unpull/'); 41 41 return $http.post('/api/flashcards/' + this.id + '/unpull/');
}; 42 42 };
Flashcard.prototype.hide = function () { 43 43 Flashcard.prototype.hide = function () {
return $http.post('/api/flashcards/' + this.id + '/hide/'); 44 44 return $http.post('/api/flashcards/' + this.id + '/hide/');
}; 45 45 };
Flashcard.prototype.unhide = function () { 46 46 Flashcard.prototype.unhide = function () {
return $http.post('/api/flashcards/' + this.id + '/unhide/'); 47 47 return $http.post('/api/flashcards/' + this.id + '/unhide/');
}; 48 48 };
Flashcard.cleanup = function () { 49 49 Flashcard.cleanup = function () {
Deck = null; 50 50 Deck = null;
FlashcardCache = []; 51 51 FlashcardCache = [];
}; 52 52 };
Flashcard.linkDeck = function(deck){ 53 53 Flashcard.linkDeck = function(deck){
Deck = deck; 54 54 Deck = deck;
} 55 55 }
56 56
57 Flashcard.prototype.edit = function () {
58
59
60 var editableText = this.formatted_text;
61
62 //$('#flashcardEditText').html(this.formatted_text);
63
64 $('.modal-trigger').leanModal({
65 dismissible: true, // Modal can be dismissed by clicking outside of the modal
66 opacity: .5, // Opacity of modal background
67 in_duration: 300, // Transition in duration
68 out_duration: 200, // Transition out duration
69 ready: function () {
70
71 $('#edit-card-input').html(editableText);
72
73
74
75 }, // Callback for Modal open
76 complete: function () {
77
78 console.log("EDIT MODAL CLOSED");
79
80 } // Callback for Modal close
81 });
82
83 };
84
85
86
87 Flashcard.prototype.refreshEditCardInput = function () {
88
89 console.log("ASDFASDFASDFASFD");
90
91
92 this.editCardText = $('#edit-card-input').text();
93
94
95 this.submit_enabled = this.editCardText.length >= 5 && this.editCardText.length <= 160;
96
97
98
99 var i = 0;
100 this.editCardBlanks = [];
101 $('#edit-card-input')[0].childNodes.forEach(function (node) {
102 node = $(node)[0];
103 if (node.tagName == 'B') {
104 var text = $(node).text();
105 var leftspaces = 0, rightspaces = 0;
106 // awful way to find the first non-space character from the left or the right. thanks.js
107 while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++;
108 while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++;
109 console.log(leftspaces, text.length);
110 if (leftspaces != text.length) $scope.editCardBlanks.push([i + leftspaces, i + text.length - rightspaces]);
111 i += text.length;
112 } else if (!node.data) {
113 i += $(node).text().length;
114 } else {
115 i += node.data.length;
116 }
117 });
118 this.editCardBlanks.sort(function (a, b) {
119 return a[0] - b[0];
120 });
121 i = 0;
122 newtext = '';
123 this.editCardBlanks.forEach(function (blank) {
124 newtext += this.editCardText.slice(i, blank[0]);
125 newtext += '<b>' + this.editCardText.slice(blank[0], blank[1]) + '</b>';
126 i = blank[1];
127 });
128 newtext += this.editCardText.slice(i);
129 //$scope.newCardFormattedText = newtext;*/
130
131
132 };
133
134
135
136
137 Flashcard.prototype.pushCard = function () {
138
139 //console.log()
140
141 var myCard = {
142 'text': $('#edit-card-input').text(),
143 'mask': this.editCardBlanks,
144 //section: this.section.id
145 };
146 if (myCard.text == '') {
147 console.log('blank flashcard not pushed:' + myCard.text);
148 return closeNewCard();
149 }
150 $http.patch('/api/flashcards/' + this.id, myCard).
151 success(function (data) {
152 console.log('flashcard pushed: ' + myCard.text);
153 if (!UserService.hasVerifiedEmail()) {
154 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
155 }
156 });
157 //return .closeNewCardModal();
158
159 }
160
161
162
Flashcard.prototype.edit = function () { 57 163 return Flashcard;
58 164 });
59 165
var editableText = this.formatted_text; 60
61
//$('#flashcardEditText').html(this.formatted_text); 62
63
$('.modal-trigger').leanModal({ 64
dismissible: true, // Modal can be dismissed by clicking outside of the modal 65
opacity: .5, // Opacity of modal background 66
in_duration: 300, // Transition in duration 67
out_duration: 200, // Transition out duration 68
ready: function () { 69
70
$('#edit-card-input').html(editableText); 71
72
73
74
}, // Callback for Modal open 75
complete: function () { 76
77
console.log("EDIT MODAL CLOSED"); 78
79
} // Callback for Modal close 80
}); 81
82
}; 83
84
85
86
Flashcard.prototype.refreshEditCardInput = function () { 87
88
console.log("ASDFASDFASDFASFD"); 89
90
91
this.editCardText = $('#edit-card-input').text(); 92
93
94
this.submit_enabled = this.editCardText.length >= 5 && this.editCardText.length <= 160; 95
96
97
98
var i = 0; 99
this.editCardBlanks = []; 100
$('#edit-card-input')[0].childNodes.forEach(function (node) { 101
node = $(node)[0]; 102
if (node.tagName == 'B') { 103
var text = $(node).text(); 104
var leftspaces = 0, rightspaces = 0; 105
// awful way to find the first non-space character from the left or the right. thanks.js 106
while (text[leftspaces] == ' ' || text[leftspaces] == '\xa0') leftspaces++; 107
while (text[text.length - 1 - rightspaces] == ' ' || text[text.length - 1 - rightspaces] == '\xa0') rightspaces++; 108
console.log(leftspaces, text.length); 109
if (leftspaces != text.length) $scope.editCardBlanks.push([i + leftspaces, i + text.length - rightspaces]); 110
i += text.length; 111
} else if (!node.data) { 112
i += $(node).text().length; 113
} else { 114
i += node.data.length; 115
} 116
}); 117
this.editCardBlanks.sort(function (a, b) { 118
return a[0] - b[0]; 119
}); 120
i = 0; 121
newtext = ''; 122
this.editCardBlanks.forEach(function (blank) { 123
newtext += this.editCardText.slice(i, blank[0]); 124
newtext += '<b>' + this.editCardText.slice(blank[0], blank[1]) + '</b>'; 125
i = blank[1]; 126
}); 127
newtext += this.editCardText.slice(i); 128
//$scope.newCardFormattedText = newtext;*/ 129
templates/flashcard.html View file @ 0c0dbdc
1 <div class="card flashy smallify black-text text-darken-2" ng-class="{'in-deck':flashcard.isInDeck()}">
2
<div class="card flashy smallify black-text text-darken-2" ng-class="{'in-deck':flashcard.isInDeck()}"> 1 3 <div class="card flashy black-text"
2 4 ng-class="{'in-deck':flashcard.isInDeck()}">
<div class="card flashy black-text" 3 5 <div class="valign-wrapper">
ng-class="{'in-deck':flashcard.isInDeck()}"> 4 6 <div class="card-content valign center-align" ng-bind-html="flashcard.formatted_text"></div>
<div class="valign-wrapper"> 5 7 </div>
8
9
10
11
12
<div class="card-content valign center-align" ng-bind-html="flashcard.formatted_text"></div> 6 13 <div class="card-overlay">
</div> 7 14 <div class="top-box no-user-select"
8 15 ng-click="flashcard.pullUnpull()">
9 16 <div class="center-me">
10 17 <i ng-if="flashcard.isInDeck()" class="fadey mdi-content-remove-circle-outline medium"></i>
11 18 <i ng-if="!flashcard.isInDeck()" class="fadey mdi-content-add-circle-outline medium"></i>
12 19 </div>
<div class="card-overlay"> 13 20 </div>
<div class="top-box no-user-select" 14 21 <div class="bottom-box no-user-select">
ng-click="flashcard.pullUnpull()"> 15 22
<div class="center-me"> 16 23
24 <div class="left-box tooltipped" data-position=" bottom" data-tooltip="Info">
25 <div class="center-me modal-trigger" href="#editModal" ng-click="flashcard.edit()"><i class="mdi-editor-border-color small"></i></div>
<i ng-if="flashcard.isInDeck()" class="fadey mdi-content-remove-circle-outline medium"></i> 17 26 </div>
27
28
29
30
<i ng-if="!flashcard.isInDeck()" class="fadey mdi-content-add-circle-outline medium"></i> 18 31 <div class="right-box tooltipped" ng-click="flashcard.hide()" data-position="bottom" data-tooltip="Hide">
</div> 19 32 <div class="center-me"><i class="mdi-action-delete small"></i></div>
</div> 20 33 </div>
<div class="bottom-box no-user-select"> 21 34
22 35 </div>
23 36 </div>
37
38
39 <!--<div id="editModal" class="modal">
40 <div class="modal-content">
41 <h4 id="flashcardEditText"></h4>
42 </div>
43 <div class="modal-footer">
44
45 </div>
46 </div>-->
47
48
49
50 <div id="editModal" class="modal row" style="max-height:none;">
51 <form id="edit-card-form">
52 <div class="modal-content col">
53 <div class="row" style="margin-bottom:0">
54 <div class="card cyan-text text-darken-2"
55 style="width:300px; height:180px; margin-bottom:0; font-size:120%;">
56 <div class="valign-wrapper">
57 <div id="edit-card-input" ng-model="newCardFormattedText" style="outline:0px solid transparent;"
58 class="card-content valign center-align"
59 contenteditable select-non-editable="true" ng-change="flashcard.refreshEditCardInput()">
60 </div>
61 </div>
62 </div>
63 </div>
64 </div>
65 <div class="col">
66 <div class="row">
67 </div>
68 <div class="row">
69 <button class="btn modal-close tooltipped" type="submit" ng-click="flashcard.pushCard()"
70 data-position="left"
71 data-delay="50" ng-class="flashcard.submit_enabled?{}:'disabled'"
72 data-tooltip="Enter">
73 Edit
74 <i class="mdi-hardware-keyboard-return right"></i>
75 </button>
76 </div>
77 <div class="row">
78 <button id="blank-selected" style="float:left" class="btn tooltipped" data-position="right" data-delay="50"
79 data-tooltip="Ctrl-B">
80 Blank Selected Text
81 </button>
82 </div>
83 <div class="row" ng-show="flashcard.editCardText" ng-style="(flashcard.editCardText.length>160)?{color:'red'}:{}">
84 {{flashcard.editCardText.length}}/160 characters
85 </div>
86 <div class="row" ng-show="flashcard.editCardText.length < 5">
87 Please write a little more!
88 </div>
89 <div class="row" ng-show="flashcard.editCardText.length > 140">
90 Good flashcards have a<br>
91 single atomic fact
92 </div>
93 </div>
94 </form>
95 </div>
96
97
98
99
100
101
102
<div class="left-box tooltipped" data-position=" bottom" data-tooltip="Info"> 24 103 <div ng-show="flashcard.isInDeck()" class="green-text" style="position:absolute; top:-9px;right:0px">
<div class="center-me modal-trigger" href="#editModal" ng-click="flashcard.edit()"><i class="mdi-editor-border-color small"></i></div> 25 104 <div class="center-me tooltipped" data-position="bottom" data-tooltip="In deck"><i
</div> 26 105 class="mdi-action-done small"></i></div>
27 106 </div>
28 107 <div ng-show="false" style="position:absolute; bottom:0px; right:5px;">
29 108 <span class="center-me">score:{{flashcard.score}}</span>
30 109 </div>
110
111
112
113
114
<div class="right-box tooltipped" ng-click="flashcard.hide()" data-position="bottom" data-tooltip="Hide"> 31 115 </div>
<div class="center-me"><i class="mdi-action-delete small"></i></div> 32 116
</div> 33
34
</div> 35
</div> 36
37
38
<!--<div id="editModal" class="modal"> 39
<div class="modal-content"> 40
<h4 id="flashcardEditText"></h4> 41
</div> 42
<div class="modal-footer"> 43
44
</div> 45
</div>--> 46
47
48
49
<div id="editModal" class="modal row" style="max-height:none;"> 50
<form id="edit-card-form"> 51
<div class="modal-content col"> 52
<div class="row" style="margin-bottom:0"> 53
<div class="card cyan-text text-darken-2" 54
style="width:300px; height:180px; margin-bottom:0; font-size:120%;"> 55
<div class="valign-wrapper"> 56
<div id="edit-card-input" ng-model="newCardFormattedText" style="outline:0px solid transparent;" 57
class="card-content valign center-align" 58
contenteditable select-non-editable="true" ng-change="flashcard.refreshEditCardInput()"> 59
</div> 60
</div> 61
</div> 62
</div> 63
</div> 64
<div class="col"> 65
<div class="row"> 66
</div> 67
<div class="row"> 68
<button class="btn modal-close tooltipped" type="submit" ng-click="flashcard.pushCard()" 69
data-position="left" 70
data-delay="50" ng-class="flashcard.submit_enabled?{}:'disabled'" 71
data-tooltip="Enter"> 72
Edit 73
<i class="mdi-hardware-keyboard-return right"></i> 74
</button> 75
</div> 76
<div class="row"> 77
<button id="blank-selected" style="float:left" class="btn tooltipped" data-position="right" data-delay="50" 78
data-tooltip="Ctrl-B"> 79
Blank Selected Text 80
</button> 81
</div> 82
<div class="row" ng-show="flashcard.editCardText" ng-style="(flashcard.editCardText.length>160)?{color:'red'}:{}"> 83
{{flashcard.editCardText.length}}/160 characters 84
</div> 85
<div class="row" ng-show="flashcard.editCardText.length < 5"> 86