Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagecell
Path: blob/master/js/utils.js
447 views
1
import $ from "jquery";
2
import utils from "base/js/utils";
3
import { URLs } from "./urls";
4
import { console } from "./console";
5
6
/* IPython url_join_encode and url_path_join is used in the cell server with URLs with hostnames, so we make it handle those correctly
7
this is a temporary kludge. A much better fix would be to introduce a kernel_base_url parameter in the kernel
8
initialization, which would default to the empty string, and would be prepended to every kernel request. Also, the
9
ws_host attribute would derive from the kernel_base_url parameter.
10
11
Right now, the IPython websocket connection urls are messed up (they prepend a phony ws_host), but that's okay because the regexp
12
pulls out the kernel id and everything is fine.
13
14
We make sure not to apply our handling multiple time (possible when
15
the embedding script is included many times).
16
*/
17
var url_parts = new RegExp("^((([^:/?#]+):)?(//([^/?#]*))?)?(.*)");
18
19
function strip_hostname(f) {
20
if (f._strip_hostname_applied) {
21
return f;
22
}
23
function wrapped() {
24
// override IPython function to account for leading protocol and hostname
25
// assume that the first argument has the part to strip off, if any
26
var hostname = "";
27
if (arguments.length > 0) {
28
var parts = arguments[0].match(url_parts);
29
hostname = parts[1]; // everything up to the url path
30
arguments[0] = parts[6]; // url path
31
}
32
return hostname + f.apply(null, arguments);
33
}
34
wrapped._strip_hostname_applied = true;
35
return wrapped;
36
}
37
38
utils.url_join_encode = strip_hostname(utils.url_join_encode);
39
utils.url_path_join = strip_hostname(utils.url_path_join);
40
41
var ID;
42
43
function cellSessionID() {
44
return (ID = ID || utils.uuid());
45
}
46
47
function sendRequest(method, url, data, callback, files) {
48
var isXDomain =
49
URLs.root !==
50
window.location.protocol + "//" + window.location.host + "/";
51
52
method = method.toUpperCase();
53
var hasFiles = false;
54
/* files code
55
if (files === undefined) {
56
files = [];
57
}
58
for (var i = 0; i < files.length; i++) {
59
if (files[i]) {
60
hasFiles = true;
61
break;
62
}
63
}
64
*/
65
var xhr = new XMLHttpRequest();
66
var fd = undefined;
67
if (method === "GET") {
68
data.rand = Math.random().toString();
69
}
70
if (method === "POST" && localStorage.accepted_tos) {
71
data.accepted_tos = "true";
72
}
73
// Format parameters to send as a string or a FormData object
74
if (window.FormData && method !== "GET") {
75
fd = new FormData();
76
for (var k in data) {
77
if (data.hasOwnProperty(k)) {
78
fd.append(k, data[k]);
79
}
80
}
81
/* files code
82
for (var i = 0; i < files.length; i++) {
83
if (files[i]) {
84
fd.append("file", files[i]);
85
}
86
}
87
*/
88
} else {
89
fd = "";
90
for (var k in data) {
91
if (data.hasOwnProperty(k)) {
92
fd +=
93
"&" +
94
encodeURIComponent(k) +
95
"=" +
96
encodeURIComponent(data[k]);
97
}
98
}
99
fd = fd.substr(1);
100
if (fd.length > 0 && method === "GET") {
101
url += "?" + fd;
102
fd = undefined;
103
}
104
}
105
if (window.FormData || !(isXDomain /*|| hasFiles*/)) {
106
// If an XMLHttpRequest is possible, use it
107
xhr.open(method, url, true);
108
xhr.withCredentials = true;
109
xhr.onreadystatechange = function () {
110
if (xhr.readyState === 4 /* DONE */ && callback) {
111
callback(xhr.responseText);
112
}
113
};
114
if (typeof fd === "string") {
115
xhr.setRequestHeader(
116
"Content-type",
117
"application/x-www-form-urlencoded"
118
);
119
}
120
xhr.send(fd);
121
} else if (method === "GET") {
122
// Use JSONP to send cross-domain GET requests
123
url += (url.indexOf("?") === -1 ? "?" : "&") + "callback=?";
124
$.getJSON(url, callback);
125
} else {
126
// Use a form submission to send POST requests
127
// Methods such as DELETE and OPTIONS will be sent as POST instead
128
var iframe = document.createElement("iframe");
129
iframe.name = utils.uuid();
130
var form = document.createElement("form", {
131
method: "POST",
132
action: url,
133
target: iframe.name,
134
});
135
if (data === undefined) {
136
data = {};
137
}
138
data.method = method;
139
for (var k in data) {
140
if (data.hasOwnProperty(k)) {
141
form.appendChild(
142
document.createElement("input", { name: k, value: data[k] })
143
);
144
}
145
}
146
form.appendChild(
147
document.createElement("input", { name: "frame", value: "on" })
148
);
149
/* file code
150
if (hasFiles) {
151
form.setAttribute("enctype", "multipart/form-data");
152
for (var i = 0; i < files.length; i++) {
153
if (files[i]) {
154
form.appendChild(files[i]);
155
}
156
}
157
}
158
*/
159
form.style.display = iframe.style.display = "none";
160
document.body.appendChild(iframe);
161
document.body.appendChild(form);
162
var listen = function (evt) {
163
if (
164
evt.source === iframe.contentWindow &&
165
evt.origin + "/" === URLs.root
166
) {
167
if (window.removeEventListener) {
168
removeEventListener("message", listen);
169
} else {
170
detachEvent("onmessage", listen);
171
}
172
callback(evt.data);
173
document.body.removeChild(iframe);
174
}
175
};
176
if (window.addEventListener) {
177
window.addEventListener("message", listen);
178
} else {
179
window.attachEvent("onmessage", listen);
180
}
181
form.submit();
182
document.body.removeChild(form);
183
}
184
}
185
186
export default {
187
always_new: utils.always_new,
188
cellSessionID: cellSessionID,
189
createElement: function (type, attrs, children) {
190
var node = document.createElement(type);
191
for (var k in attrs) {
192
if (attrs.hasOwnProperty(k)) {
193
node.setAttribute(k, attrs[k]);
194
}
195
}
196
if (children) {
197
for (var i = 0; i < children.length; i++) {
198
if (typeof children[i] == "string") {
199
node.appendChild(document.createTextNode(children[i]));
200
} else {
201
node.appendChild(children[i]);
202
}
203
}
204
}
205
return node;
206
},
207
fixConsole: utils.fixConsole,
208
/* var p = proxy(['list', 'of', 'methods'])
209
will save any method calls in the list. At some later time, you can invoke
210
each method on an object by doing p._run_callbacks(my_obj) */
211
proxy: function (methods) {
212
var proxy = { _callbacks: [] };
213
$.each(methods, function (i, method) {
214
proxy[method] = function () {
215
proxy._callbacks.push([method, arguments]);
216
console.log("stored proxy for " + method);
217
};
218
});
219
proxy._run_callbacks = function (obj) {
220
$.each(proxy._callbacks, function (i, cb) {
221
obj[cb[0]].apply(obj, cb[1]);
222
});
223
};
224
return proxy;
225
},
226
sendRequest: sendRequest,
227
simpleTimer: function () {
228
var t = new Date().getTime();
229
console.debug("starting timer from " + t);
230
return function (reset) {
231
var old_t = t;
232
var new_t = new Date().getTime();
233
if (reset) {
234
t = new_t;
235
}
236
return new_t - old_t + " ms";
237
};
238
},
239
// throttle is from:
240
// Underscore.js 1.4.3
241
// http://underscorejs.org
242
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
243
// Underscore may be freely distributed under the MIT license.
244
// Returns a function, that, when invoked, will only be triggered at most once
245
// during a given window of time.
246
throttle: function (func, wait) {
247
var context, args, timeout, result;
248
var previous = 0;
249
var later = function () {
250
previous = new Date();
251
timeout = null;
252
result = func.apply(context, args);
253
};
254
return function () {
255
var now = new Date();
256
var remaining = wait - (now - previous);
257
context = this;
258
args = arguments;
259
if (remaining <= 0) {
260
clearTimeout(timeout);
261
timeout = null;
262
previous = now;
263
result = func.apply(context, args);
264
} else if (!timeout) {
265
timeout = setTimeout(later, remaining);
266
}
267
return result;
268
};
269
},
270
uuid: utils.uuid,
271
};
272
273