-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
122 lines (102 loc) · 3.61 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
var rfile = require("rfile");
var iframe = require("iframe");
var blocklyBrowserCode = require("./Blockly");
var iframeHtml = rfile("./lib/frame.html");
function getWindowFromElement(element) {
var doc = element.ownerDocument;
return doc.defaultView || doc.parentWindow;
}
function createWindowFromIframe(element) {
var win = getWindowFromElement(element);
var callbackKey = "create-blockly-" + (new Date).getTime();
var iframeWin = null;
win[callbackKey] = function(callbackWin) {
delete win[callbackKey];
iframeWin = callbackWin;
};
iframe({
container: element,
html: iframeHtml.replace("{{callbackKey}}", JSON.stringify(callbackKey))
});
return iframeWin;
}
function createMockWindowForBlockly() {
return {document: {documentElement: {}}};
}
function instantiateBrowserCode(code, window) {
var mockGoog = {require: function(){}, provide: function(){}};
var creator = new Function(["window", "document", "Blockly", "goog"], code);
creator.apply(window, [window, window.document, window.Blockly, mockGoog]);
}
function hookInjectToEnsureStylesCascade(Blockly, win) {
var originalInject = Blockly.inject;
Blockly.inject = function inject() {
originalInject.apply(Blockly, arguments);
var style = win.document.getElementById("create-blockly-iframe-style");
style.parentNode.appendChild(style);
}
}
function createBlocklySync(options) {
options = options || {};
// Parse Blockly-specific configuration options.
var injectOptions = {};
var createOptionsKeys = [
"container",
"extensions"
];
for (var key in options) {
if (options.hasOwnProperty(key) && createOptionsKeys.indexOf(key) < 0) {
injectOptions[key] = options[key];
}
}
// If options.container is given, prepare to inject it using the
// resizable iframe method.
// http://code.google.com/p/blockly/wiki/InjectingResizable
var win = createMockWindowForBlockly();
var container = null;
if ("container" in options) {
if (!options.container) throw new Error("container must exist when using options.container");
container = options.container;
win = createWindowFromIframe(container);
}
// Evaluate the Blockly code in this iframe window. Ensure that
// Blockly.inject() moves the inline <style> tag below Blockly's inline
// styles to preserve basic attributes like transparent background.
instantiateBrowserCode(blocklyBrowserCode, win);
var Blockly = win.Blockly;
if (container) {
hookInjectToEnsureStylesCascade(Blockly, win);
}
// If options.extensions are given, evaluate their code in the same
// window context on this instance of Blockly. This is equivalent to
// injecting <script> tags for these files.
if (options.extensions) {
var extensions = options.extensions.slice(0);
while (extensions.length) {
var extensionBrowserCode = extensions.pop();
instantiateBrowserCode(extensionBrowserCode, win);
}
}
// If a container was given, the iframe is already created. Auto-inject
// Blockly into the document body in that iframe window.
if (container) {
Blockly.inject(win.document.body, injectOptions);
}
return win;
}
function createBlockly(options, callback) {
// If a callback is given, do this async. The main benefit of this is that
// you get a direct reference to the window that Blockly was created on.
if (callback) {
try {
var win = createBlocklySync(options);
callback(null, win.Blockly, win);
} catch(err) {
callback(err)
}
// Otherwise just synchronously return Blockly, no window.
} else {
return createBlocklySync(options).Blockly;
}
}
module.exports = createBlockly;