Commit 7ef9e631f17e55dbcf91b3a35eba946d3f88ccf3

Authored by Andrew Buss
1 parent 6b261ad25f

allow static dir

Showing 7 changed files with 522 additions and 40 deletions Inline Diff

*~ 1 1 *~
venv* 2 2 venv*
static* 3
*.pyc 4 3 *.pyc
.idea* 5 4 .idea*
.*.swp 6 5 .*.swp
.*.swo 7 6 .*.swo
.*.swn 8 7 .*.swn
*.sqlite3 9 8 *.sqlite3
secrets 10 9 secrets
.coverage 11 10 .coverage
htmlcov* 12 11 htmlcov*
sass/*.css 13 12 sass/*.css
all: styles/materialize.css styles/flashier.css fixjsstyle 1 1 all: styles/materialize.css styles/flashier.css fixjsstyle
2 2
JS_SOURCES = config.js $(wildcard scripts/*{Controller,Service,Directive}.js) 3 3 JS_SOURCES = config.js $(wildcard scripts/*Controller.js) $(wildcard scripts/*Directive.js) $(wildcard scripts/*Service.js)
4 4
5 print-%:
6 @echo '$*=$($*)'
7
styles/materialize.css: .PHONY 5 8 styles/materialize.css: .PHONY
sassc sass/materialize.scss styles/materialize.css 6 9 sassc sass/materialize.scss styles/materialize.css
7 10
styles/flashier.css: sass/flashier.scss 8 11 styles/flashier.css: sass/flashier.scss
sassc sass/flashier.scss styles/flashier.css 9 12 sassc sass/flashier.scss styles/flashier.css
10 13
fixjsstyle: .PHONY 11 14 fixjsstyle: .PHONY
$(foreach sourcefile,$(JS_SOURCES),expand $(sourcefile) | sponge > $(sourcefile);) 12 15 $(foreach sourcefile,$(JS_SOURCES),expand $(sourcefile) | sponge $(sourcefile);)
scripts/ResetPasswordController.js View file @ 7ef9e63
angular.module('flashy.ResetPasswordController', ['ui.router']). 1 1 angular.module('flashy.ResetPasswordController', ['ui.router']).
2 2
controller('ResetPasswordController', ['$scope', '$state', '$http', '$timeout', 3 3 controller('ResetPasswordController', ['$scope', '$state', '$http', '$timeout',
function($scope, $state, $http, $timeout) { 4 4 function($scope, $state, $http, $timeout) {
'use strict'; 5 5 'use strict';
var url = document.location.href.split('/'); 6 6 var url = document.location.href.split('/');
var token = url[url.length - 1]; 7 7 var token = url[url.length - 1];
var uid = url[url.length - 2]; 8 8 var uid = url[url.length - 2];
$scope.error = false; 9 9 $scope.error = false;
$scope.success = false; 10 10 $scope.success = false;
$scope.mismatch = false; 11 11 $scope.mismatch = false;
$scope.unacceptable = false; 12 12 $scope.unacceptable = false;
/*if(token == 'resetpassword') { 13 13 /*if(token == 'resetpassword') {
$state.go('login'); 14 14 $state.go('login');
}*/ 15 15 }*/
console.log('RESETTING'); 16 16 console.log('RESETTING');
$scope.confirmResetPass = function() { 17 17 $scope.confirmResetPass = function() {
if ($scope.newPassword.length < 8) { 18 18 if ($scope.newPassword.length < 8) {
$scope.unacceptable = true; 19 19 $scope.unacceptable = true;
return; 20 20 return;
} 21 21 }
if ($scope.newPassword != $scope.confirmPassword) { 22 22 if ($scope.newPassword != $scope.confirmPassword) {
$scope.mismatch = true; 23 23 $scope.mismatch = true;
$scope.confirmPassword.$setPristine(); 24 24 $scope.confirmPassword.$setPristine();
console.log('mismatch'); 25 25 console.log('mismatch');
return; 26 26 return;
} 27 27 }
/*password passes local tests*/ 28 28 /*password passes local tests*/
$http.post('/api/reset_password/', JSON.stringify({ 29 29 $http.post('/api/reset_password/', JSON.stringify({
'uid': uid, 30 30 'uid': uid,
'token': token, 31 31 'token': token,
'new_password': $scope.newPassword 32 32 'new_password': $scope.newPassword
})) 33 33 }))
.success(function(data) { 34 34 .success(function(data) {
$scope.error = false; 35 35 $scope.error = false;
$scope.success = true; 36 36 $scope.success = true;
//$state.go('resetpasssuccess'); 37 37 //$state.go('resetpasssuccess');
$timeout(function($state) { 38 38 $timeout(function($state) {
$state.go('login'); 39 39 $state.go('login');
}, 1000); 40 40 }, 1000);
console.log(data); 41 41 console.log(data);
}) 42 42 })
.error(function(data, status, header, config) { 43 43 .error(function(data, status, header, config) {
$scope.error = true; 44 44 $scope.error = true;
$scope.success = false; 45 45 $scope.success = false;
$scope.mismatch = false; 46 46 $scope.mismatch = false;
$scope.unacceptable = false; 47 47 $scope.unacceptable = false;
console.log(data); 48 48 console.log(data);
}); 49 49 });
}; 50 50 };
$scope.cancelReset = function() { 51 51 $scope.cancelReset = function() {
$state.go('login'); 52 52 $state.go('login');
}; 53 53 };
}]); 54 54 }]);
55 55
scripts/SettingsController.js View file @ 7ef9e63
angular.module('flashy.SettingsController', ['ui.router']). 1 1 angular.module('flashy.SettingsController', ['ui.router']).
2 2
controller('SettingsController', function($scope) { 3 3 controller('SettingsController', function($scope) {
4 4
5 5
$scope.changePassword = function(oldPassword, newPassword, confirmedNewPassword) { 6 6 $scope.changePassword = function(oldPassword, newPassword, confirmedNewPassword) {
7 7
8 8
9 9
scripts/StudyController.js View file @ 7ef9e63
angular.module('flashy.StudyController', ['ui.router']). 1 1 angular.module('flashy.StudyController', ['ui.router']).
2 2
controller('StudyController', ['$scope', '$stateParams', '$state', '$http', 'UserService', 3 3 controller('StudyController', ['$scope', '$stateParams', '$state', '$http', 'UserService',
function($scope, $stateParams, $state, $http, UserService) { 4 4 function($scope, $stateParams, $state, $http, UserService) {
console.log('Flashy study controller content in this file. also hell0'); 5 5 console.log('Flashy study controller content in this file. also hell0');
sectionId = $stateParams.sectionId; 6 6 sectionId = $stateParams.sectionId;
$scope.isParamOpen = true; 7 7 $scope.isParamOpen = true;
8 8
$(document).ready(function() { 9 9 $(document).ready(function() {
$('.datepicker').pickadate({ 10 10 $('.datepicker').pickadate({
selectMonths: true, // Creates a dropdown to control month 11 11 selectMonths: true, // Creates a dropdown to control month
selectYears: 15 // Creates a dropdown of 15 years to control year 12 12 selectYears: 15 // Creates a dropdown of 15 years to control year
}); 13 13 });
14 14
$('select').material_select(); 15 15 $('select').material_select();
}); 16 16 });
17 17
$scope.UserService = UserService; 18 18 $scope.UserService = UserService;
$scope.isParamOpen = true; 19 19 $scope.isParamOpen = true;
20 20
console.log($scope.UserService.getUserData().sections); 21 21 console.log($scope.UserService.getUserData().sections);
22 22
$scope.toggleSectionToStudy = function(id) { 23 23 $scope.toggleSectionToStudy = function(id) {
console.log('toggle sect', id); 24 24 console.log('toggle sect', id);
$scope.sectionToStudy = id; 25 25 $scope.sectionToStudy = id;
}; 26 26 };
27 27
$scope.openParams = function() { 28 28 $scope.openParams = function() {
$scope.isParamOpen = !$scope.isParamOpen; 29 29 $scope.isParamOpen = !$scope.isParamOpen;
}; 30 30 };
31 31
$scope.fetchQuiz = function(a, b) { 32 32 $scope.fetchQuiz = function(a, b) {
//console.log($scope.startDate, $scope.endDate); 33 33 //console.log($scope.startDate, $scope.endDate);
console.log(a, b); 34 34 console.log(a, b);
}; 35 35 };
36 36
/* 37 37 /*
$scope.fetchQuiz = function() { 38 38 $scope.fetchQuiz = function() {
console.log('fetching quiz...'); 39 39 console.log('fetching quiz...');
var studyRequest = { 40 40 var studyRequest = {
'sections': ($scope.sectionToStudy == null) ? [] : [$scope.sectionToStudy], 41 41 'sections': ($scope.sectionToStudy == null) ? [] : [$scope.sectionToStudy],
'material_date_begin':, 42 42 'material_date_begin':,
'material_date_end': 43 43 'material_date_end':
}; 44 44 };
45 45
// $http.post('/api/study/', studyRequest). 46 46 // $http.post('/api/study/', studyRequest).
//TODO 47 47 //TODO
}; 48 48 };
*/ 49 49 */
50 50
/* OLD STUFF :in case you still neeed it */ 51 51 /* OLD STUFF :in case you still neeed it */
// Flashcard content 52 52 // Flashcard content
$scope.htmlContent = 'sample text here longwordddddddddddddddddddddddddddd hello there from js review ctrl alwkejflakewjflk awjkefjkwefjlkea jfkewjaweajkakwef jk fjeawkafj kaewjf jawekfj akwejfk '; 53 53 $scope.htmlContent = 'sample text here longwordddddddddddddddddddddddddddd hello there from js review ctrl alwkejflakewjflk awjkefjkwefjlkea jfkewjaweajkakwef jk fjeawkafj kaewjf jawekfj akwejfk ';
//single card 54 54 //single card
$scope.samples = 55 55 $scope.samples =
{ 56 56 {
'name': 'lol', 57 57 'name': 'lol',
'text': 'sample text here 111111 woo hoo I think it works', 58 58 'text': 'sample text here 111111 woo hoo I think it works',
'mask': [[0, 6], [16, 23]] 59 59 'mask': [[0, 6], [16, 23]]
}; 60 60 };
61 61
// get text to display as array 62 62 // get text to display as array
$scope.displayText = []; 63 63 $scope.displayText = [];
// get answers to blanks as array 64 64 // get answers to blanks as array
$scope.blankText = []; 65 65 $scope.blankText = [];
var start = 0; // where to start next string break 66 66 var start = 0; // where to start next string break
for (var i = 0; i < $scope.samples.mask.length; i++) { 67 67 for (var i = 0; i < $scope.samples.mask.length; i++) {
$scope.displayText.push($scope.samples.text.substring(start, $scope.samples.mask[i][0])); 68 68 $scope.displayText.push($scope.samples.text.substring(start, $scope.samples.mask[i][0]));
$scope.blankText.push($scope.samples.text.substring($scope.samples.mask[i][0], $scope.samples.mask[i][1])); 69 69 $scope.blankText.push($scope.samples.text.substring($scope.samples.mask[i][0], $scope.samples.mask[i][1]));
start = $scope.samples.mask[i][1]; 70 70 start = $scope.samples.mask[i][1];
} 71 71 }
if (start != $scope.samples.mask.length - 1) 72 72 if (start != $scope.samples.mask.length - 1)
$scope.displayText.push($scope.samples.text.substring(start)); 73 73 $scope.displayText.push($scope.samples.text.substring(start));
static/js/angular-contenteditable.js View file @ 7ef9e63
File was created 1 /**
2 * @see http://docs.angularjs.org/guide/concepts
3 * @see http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
4 * @see https://github.com/angular/angular.js/issues/528#issuecomment-7573166
5 */
6
7 angular.module('contenteditable', [])
8 .directive('contenteditable', ['$timeout', function($timeout) { return {
9 restrict: 'A',
10 require: '?ngModel',
11 link: function(scope, element, attrs, ngModel) {
12 // don't do anything unless this is actually bound to a model
13 if (!ngModel) {
14 return
15 }
16
17 // options
18 var opts = {}
19 angular.forEach([
20 'stripBr',
21 'noLineBreaks',
22 'selectNonEditable',
23 'moveCaretToEndOnChange',
24 ], function(opt) {
25 var o = attrs[opt]
26 opts[opt] = o && o !== 'false'
27 })
28
29 // view -> model
30 element.bind('input', function(e) {
31 scope.$apply(function() {
32 var html, html2, rerender
33 html = element.html()
34 rerender = false
35 if (opts.stripBr) {
36 html = html.replace(/<br>$/, '')
37 }
38 if (opts.noLineBreaks) {
39 html2 = html.replace(/<div>/g, '').replace(/<br>/g, '').replace(/<\/div>/g, '')
40 if (html2 !== html) {
41 rerender = true
42 html = html2
43 }
44 }
45 ngModel.$setViewValue(html)
46 if (rerender) {
47 ngModel.$render()
48 }
49 if (html === '') {
50 // the cursor disappears if the contents is empty
51 // so we need to refocus
52 $timeout(function(){
53 element[0].blur()
54 element[0].focus()
55 })
56 }
57 })
58 })
59
60 // model -> view
61 var oldRender = ngModel.$render
62 ngModel.$render = function() {
63 var el, el2, range, sel
64 if (!!oldRender) {
65 oldRender()
66 }
67 element.html(ngModel.$viewValue || '')
68 if (opts.moveCaretToEndOnChange) {
69 el = element[0]
70 range = document.createRange()
71 sel = window.getSelection()
72 if (el.childNodes.length > 0) {
73 el2 = el.childNodes[el.childNodes.length - 1]
74 range.setStartAfter(el2)
75 } else {
76 range.setStartAfter(el)
77 }
78 range.collapse(true)
79 sel.removeAllRanges()
80 sel.addRange(range)
81 }
82 }
83 if (opts.selectNonEditable) {
84 element.bind('click', function(e) {
85 var range, sel, target
86 target = e.toElement
87 if (target !== this && angular.element(target).attr('contenteditable') === 'false') {
88 range = document.createRange()
89 sel = window.getSelection()
90 range.setStartBefore(target)
91 range.setEndAfter(target)
92 sel.removeAllRanges()
93 sel.addRange(range)
94 }
static/js/angular-websocket.js View file @ 7ef9e63
File was created 1 (function() {
2 'use strict';
3
4 var noop = angular.noop;
5 var objectFreeze = (Object.freeze) ? Object.freeze : noop;
6 var objectDefineProperty = Object.defineProperty;
7 var isString = angular.isString;
8 var isFunction = angular.isFunction;
9 var isDefined = angular.isDefined;
10 var isObject = angular.isObject;
11 var isArray = angular.isArray;
12 var forEach = angular.forEach;
13 var arraySlice = Array.prototype.slice;
14 // ie8 wat
15 if (!Array.prototype.indexOf) {
16 Array.prototype.indexOf = function(elt /*, from*/) {
17 var len = this.length >>> 0;
18 var from = Number(arguments[1]) || 0;
19 from = (from < 0) ? Math.ceil(from) : Math.floor(from);
20 if (from < 0) {
21 from += len;
22 }
23
24 for (; from < len; from++) {
25 if (from in this && this[from] === elt) { return from; }
26 }
27 return -1;
28 };
29 }
30
31 // $WebSocketProvider.$inject = ['$rootScope', '$q', '$timeout', '$websocketBackend'];
32 function $WebSocketProvider($rootScope, $q, $timeout, $websocketBackend) {
33
34 function $WebSocket(url, protocols, options) {
35 if (!options && isObject(protocols) && !isArray(protocols)) {
36 options = protocols;
37 protocols = undefined;
38 }
39
40 this.protocols = protocols;
41 this.url = url || 'Missing URL';
42 this.ssl = /(wss)/i.test(this.url);
43
44 // this.binaryType = '';
45 // this.extensions = '';
46 // this.bufferedAmount = 0;
47 // this.trasnmitting = false;
48 // this.buffer = [];
49
50 // TODO: refactor options to use isDefined
51 this.scope = options && options.scope || $rootScope;
52 this.rootScopeFailover = options && options.rootScopeFailover && true;
53 this.useApplyAsync = options && options.useApplyAsync || false;
54 this.initialTimeout = options && options.initialTimeout || 500; // 500ms
55 this.maxTimeout = options && options.maxTimeout || 5 * 60 * 1000; // 5 minutes
56 this.reconnectIfNotNormalClose = options && options.reconnectIfNotNormalClose || false;
57
58 this._reconnectAttempts = 0;
59 this.sendQueue = [];
60 this.onOpenCallbacks = [];
61 this.onMessageCallbacks = [];
62 this.onErrorCallbacks = [];
63 this.onCloseCallbacks = [];
64
65 objectFreeze(this._readyStateConstants);
66
67 if (url) {
68 this._connect();
69 } else {
70 this._setInternalState(0);
71 }
72
73 }
74
75
76 $WebSocket.prototype._readyStateConstants = {
77 'CONNECTING': 0,
78 'OPEN': 1,
79 'CLOSING': 2,
80 'CLOSED': 3,
81 'RECONNECT_ABORTED': 4
82 };
83
84 $WebSocket.prototype._normalCloseCode = 1000;
85
86 $WebSocket.prototype._reconnectableStatusCodes = [
87 4000
88 ];
89
90 $WebSocket.prototype.safeDigest = function safeDigest(autoApply) {
91 if (autoApply && !this.scope.$$phase) {
92 this.scope.$digest();
93 }
94 };
95
96 $WebSocket.prototype.bindToScope = function bindToScope(scope) {
97 var self = this;
98 if (scope) {
99 this.scope = scope;
100 if (this.rootScopeFailover) {
101 this.scope.$on('$destroy', function() {
102 self.scope = $rootScope;
103 });
104 }
105 }
106 return self;
107 };
108
109 $WebSocket.prototype._connect = function _connect(force) {
110 if (force || !this.socket || this.socket.readyState !== this._readyStateConstants.OPEN) {
111 this.socket = $websocketBackend.create(this.url, this.protocols);
112 this.socket.onmessage = angular.bind(this, this._onMessageHandler);
113 this.socket.onopen = angular.bind(this, this._onOpenHandler);
114 this.socket.onerror = angular.bind(this, this._onErrorHandler);
115 this.socket.onclose = angular.bind(this, this._onCloseHandler);
116 }
117 };
118
119 $WebSocket.prototype.fireQueue = function fireQueue() {
120 while (this.sendQueue.length && this.socket.readyState === this._readyStateConstants.OPEN) {
121 var data = this.sendQueue.shift();
122
123 this.socket.send(
124 isString(data.message) ? data.message : JSON.stringify(data.message)
125 );
126 data.deferred.resolve();
127 }
128 };
129
130 $WebSocket.prototype.notifyOpenCallbacks = function notifyOpenCallbacks(event) {
131 for (var i = 0; i < this.onOpenCallbacks.length; i++) {
132 this.onOpenCallbacks[i].call(this, event);
133 }
134 };
135
136 $WebSocket.prototype.notifyCloseCallbacks = function notifyCloseCallbacks(event) {
137 for (var i = 0; i < this.onCloseCallbacks.length; i++) {
138 this.onCloseCallbacks[i].call(this, event);
139 }
140 };
141
142 $WebSocket.prototype.notifyErrorCallbacks = function notifyErrorCallbacks(event) {
143 for (var i = 0; i < this.onErrorCallbacks.length; i++) {
144 this.onErrorCallbacks[i].call(this, event);
145 }
146 };
147
148 $WebSocket.prototype.onOpen = function onOpen(cb) {
149 this.onOpenCallbacks.push(cb);
150 return this;
151 };
152
153 $WebSocket.prototype.onClose = function onClose(cb) {
154 this.onCloseCallbacks.push(cb);
155 return this;
156 };
157
158 $WebSocket.prototype.onError = function onError(cb) {
159 this.onErrorCallbacks.push(cb);
160 return this;
161 };
162
163
164 $WebSocket.prototype.onMessage = function onMessage(callback, options) {
165 if (!isFunction(callback)) {
166 throw new Error('Callback must be a function');
167 }
168
169 if (options && isDefined(options.filter) && !isString(options.filter) && !(options.filter instanceof RegExp)) {
170 throw new Error('Pattern must be a string or regular expression');
171 }
172
173 this.onMessageCallbacks.push({
174 fn: callback,
175 pattern: options ? options.filter : undefined,
176 autoApply: options ? options.autoApply : true
177 });
178 return this;
179 };
180
181 $WebSocket.prototype._onOpenHandler = function _onOpenHandler(event) {
182 this._reconnectAttempts = 0;
183 this.notifyOpenCallbacks(event);
184 this.fireQueue();
185 };
186
187 $WebSocket.prototype._onCloseHandler = function _onCloseHandler(event) {
188 this.notifyCloseCallbacks(event);
189 if ((this.reconnectIfNotNormalClose && event.code !== this._normalCloseCode) || this._reconnectableStatusCodes.indexOf(event.code) > -1) {
190 this.reconnect();
191 }
192 };
193
194 $WebSocket.prototype._onErrorHandler = function _onErrorHandler(event) {
195 this.notifyErrorCallbacks(event);
196 };
197
198 $WebSocket.prototype._onMessageHandler = function _onMessageHandler(message) {
199 var pattern;
200 var self = this;
201 var currentCallback;
202 for (var i = 0; i < self.onMessageCallbacks.length; i++) {
203 currentCallback = self.onMessageCallbacks[i];
204 pattern = currentCallback.pattern;
205 if (pattern) {
206 if (isString(pattern) && message.data === pattern) {
207 applyAsyncOrDigest(currentCallback.fn, currentCallback.autoApply, message);
208 }
209 else if (pattern instanceof RegExp && pattern.exec(message.data)) {
210 applyAsyncOrDigest(currentCallback.fn, currentCallback.autoApply, message);
211 }
212 }
213 else {
214 applyAsyncOrDigest(currentCallback.fn, currentCallback.autoApply, message);
215 }
216 }
217
218 function applyAsyncOrDigest(callback, autoApply, args) {
219 args = arraySlice.call(arguments, 2);
220 if (self.useApplyAsync) {
221 self.scope.$applyAsync(function() {
222 callback.apply(self, args);
223 });
224 } else {
225 callback.apply(self, args);
226 self.safeDigest(autoApply);
227 }
228 }
229
230 };
231
232 $WebSocket.prototype.close = function close(force) {
233 if (force || !this.socket.bufferedAmount) {
234 this.socket.close();
235 }
236 return this;
237 };
238
239 $WebSocket.prototype.send = function send(data) {
240 var deferred = $q.defer();
241 var self = this;
242 var promise = cancelableify(deferred.promise);
243
244 if (self.readyState === self._readyStateConstants.RECONNECT_ABORTED) {
245 deferred.reject('Socket connection has been closed');
246 }
247 else {
248 self.sendQueue.push({
249 message: data,
250 deferred: deferred
251 });
252 self.fireQueue();
253 }
254
255 // Credit goes to @btford
256 function cancelableify(promise) {
257 promise.cancel = cancel;
258 var then = promise.then;
259 promise.then = function() {
260 var newPromise = then.apply(this, arguments);
261 return cancelableify(newPromise);
262 };
263 return promise;
264 }
265
266 function cancel(reason) {
267 self.sendQueue.splice(self.sendQueue.indexOf(data), 1);
268 deferred.reject(reason);
269 return self;
270 }
271
272 if ($websocketBackend.isMocked && $websocketBackend.isMocked() &&
273 $websocketBackend.isConnected(this.url)) {
274 this._onMessageHandler($websocketBackend.mockSend());
275 }
276
277 return promise;
278 };
279
280 $WebSocket.prototype.reconnect = function reconnect() {
281 this.close();
282
283 var backoffDelay = this._getBackoffDelay(++this._reconnectAttempts);
284
285 var backoffDelaySeconds = backoffDelay / 1000;
286 console.log('Reconnecting in ' + backoffDelaySeconds + ' seconds');
287
288 $timeout(angular.bind(this, this._connect), backoffDelay);
289
290 return this;
291 };
292 // Exponential Backoff Formula by Prof. Douglas Thain
293 // http://dthain.blogspot.co.uk/2009/02/exponential-backoff-in-distributed.html
294 $WebSocket.prototype._getBackoffDelay = function _getBackoffDelay(attempt) {
295 var R = Math.random() + 1;
296 var T = this.initialTimeout;
297 var F = 2;
298 var N = attempt;
299 var M = this.maxTimeout;
300
301 return Math.floor(Math.min(R * T * Math.pow(F, N), M));
302 };
303
304 $WebSocket.prototype._setInternalState = function _setInternalState(state) {
305 if (Math.floor(state) !== state || state < 0 || state > 4) {
306 throw new Error('state must be an integer between 0 and 4, got: ' + state);
307 }
308
309 // ie8 wat
310 if (!objectDefineProperty) {
311 this.readyState = state || this.socket.readyState;
312 }
313 this._internalConnectionState = state;
314
315
316 forEach(this.sendQueue, function(pending) {
317 pending.deferred.reject('Message cancelled due to closed socket connection');
318 });