Skip to content
This repository was archived by the owner on Nov 22, 2021. It is now read-only.

Commit c339584

Browse files
author
Ke, Mingze
committed
Added direct QR code
1 parent 1494b43 commit c339584

12 files changed

+263
-14
lines changed

code.js

+34-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ var slice = Array.prototype.slice;
2727

2828
var baseUrl = baseUrl || '.';
2929

30+
var storage = new JSONStorage('https://glowing-fire-4998.firebaseio.com/hyproto');
31+
3032
/**
3133
* Create a namespace for the application.
3234
*/
@@ -229,7 +231,7 @@ Code.loadBlocks = function(defaultXml) {
229231
// Restarting Firefox fixes this, so it looks like a bug.
230232
var loadOnce = null;
231233
}
232-
if ('BlocklyStorage' in window && window.location.hash.length > 1) {
234+
if ('BlocklyStorage' in window && BlocklyStorage.isLinkUrl()) {
233235
// An href with #key trigers an AJAX call to retrieve saved blocks.
234236
BlocklyStorage.retrieveXml(window.location.hash.substring(1));
235237
} else if (loadOnce) {
@@ -761,6 +763,10 @@ Code.getToolBox = function (toolboxXML) {
761763
return new XMLSerializer().serializeToString(toolboxXML);
762764
};
763765

766+
Code.getUrlParts = function () {
767+
return (location.protocol + '//' + location.host + location.pathname).split('/');
768+
};
769+
764770
/**
765771
* Initialize Blockly. Called on page load.
766772
*/
@@ -827,10 +833,34 @@ Code.init = function(toolbox) {
827833

828834
Code.tabClick(Code.selected);
829835

836+
Code.bindClick('qrButton', function () {
837+
var img = document.querySelector('#qrImg'),
838+
ctx = Code.getContext();
839+
840+
launcher.loadTemplate('./templates/' + ctx.tpl + '.html', function (data) {
841+
if (ctx.jsPreprocessor === 'babel') {
842+
data.js = Code.transform(ctx.data.js);
843+
} else {
844+
data.js = ctx.data.js;
845+
}
846+
847+
launcher.liveview(storage, data, function (url) {
848+
url = window.encodeURIComponent(url);
849+
if (img === null) {
850+
img = document.createElement('img');
851+
img.id = 'qrImg';
852+
img.src = 'http://chart.apis.google.com/chart?cht=qr&chl=' + url + '&chs=300x300';
853+
document.querySelector('#openModal').children[0].appendChild(img);
854+
} else {
855+
img.src = 'http://chart.apis.google.com/chart?cht=qr&chl=' + url + '&chs=300x300';
856+
}
857+
});
858+
});
859+
});
860+
830861
Code.bindClick('linkToBin', function () {
831-
var urls = (location.protocol + '//' + location.host + location.pathname).split('/');
832-
var ctx = Code.getContext();
833-
urls.pop();
862+
var ctx = Code.getContext(),
863+
urls = Code.getUrlParts().pop();
834864
localStorage.setItem(urls.join('/') + '/launcher.html', JSON.stringify(ctx));
835865
});
836866

css/dialog.css

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.modalDialog {
2+
position: fixed;
3+
font-family: Arial, Helvetica, sans-serif;
4+
top: 0;
5+
right: 0;
6+
bottom: 0;
7+
left: 0;
8+
background: rgba(0, 0, 0, 0.8);
9+
z-index: 99999;
10+
opacity: 0;
11+
-webkit-transition: opacity 400ms ease-in;
12+
-moz-transition: opacity 400ms ease-in;
13+
transition: opacity 400ms ease-in;
14+
pointer-events: none;
15+
}
16+
17+
.modalDialog:target {
18+
opacity: 1;
19+
pointer-events: auto;
20+
}
21+
22+
.modalDialog > div {
23+
width: 300px;
24+
position: relative;
25+
margin: 10% auto;
26+
padding: 5px 20px 13px 20px;
27+
border-radius: 10px;
28+
background: #ffffff;
29+
}
30+
31+
.close {
32+
background: #606061;
33+
color: #FFFFFF;
34+
line-height: 25px;
35+
position: absolute;
36+
right: -12px;
37+
text-align: center;
38+
top: -10px;
39+
width: 24px;
40+
text-decoration: none;
41+
font-weight: bold;
42+
-webkit-border-radius: 12px;
43+
-moz-border-radius: 12px;
44+
border-radius: 12px;
45+
-moz-box-shadow: 1px 1px 3px #000;
46+
-webkit-box-shadow: 1px 1px 3px #000;
47+
box-shadow: 1px 1px 3px #000;
48+
}
49+
50+
.close:hover {
51+
background: #00d9ff;
52+
}

css/style.css

+5-5
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ td#copyCode div {
569569
border-radius: 5px;
570570
}
571571

572-
#linkToBin {
572+
.linkButton {
573573
display: inline-block;
574574
font-size: 16px;
575575
color: #000;
@@ -583,22 +583,22 @@ td#copyCode div {
583583
vertical-align: bottom;
584584
}
585585

586-
#linkToBin img {
586+
.linkButton img {
587587
height: 17px;
588588
margin-bottom: -2px;
589589
margin-right: 3px;
590590
}
591591

592-
#linkToBin:link {
592+
.linkButton:link {
593593
color: #000;
594594
text-decoration: none;
595595
}
596596

597-
#linkToBin:hover {
597+
.linkButton:hover {
598598
opacity:1;
599599
}
600600

601-
#linkToBin:active {
601+
.linkButton:active {
602602
opacity: .8;
603603
}
604604

index.html

+2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
<link rel="stylesheet" href="css/iconfont.css">
2020
<link rel="stylesheet" href="css/style.css">
2121
<link rel="stylesheet" href="css/blockly.css">
22+
<link rel="stylesheet" href="css/dialog.css">
2223

2324
<script src="components/blockly-src/blockly_compressed.js"></script>
2425
<script src="components/blockly-src/blocks_compressed.js"></script>
2526
<script src="components/blockly-src/javascript_compressed.js"></script>
2627
<script src="components/webcomponentsjs/webcomponents-lite.min.js"></script>
2728
<script src="lib/handlebars-3.0.3.min.js"></script>
29+
<script src="lib/JSONStorage.js"></script>
2830
<script src="storage.js"></script>
2931
<script src="launcher.js"></script>
3032
<script src="code.js"></script>

launcher.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
}
1111
*/
1212

13-
+(function (window, document) {
13+
+(function (window, document, location) {
1414

1515
'use strict';
1616

@@ -127,6 +127,18 @@
127127
frame.contentWindow.document.open();
128128
frame.contentWindow.document.write(code);
129129
frame.contentWindow.document.close();
130+
},
131+
132+
liveview: function (storage, data, callback) {
133+
var code = assembleHtml(data.head, data.body, data.css, data.js),
134+
parts = (location.protocol + '//' + location.host + location.pathname).split('/');
135+
136+
parts.pop();
137+
storage.link(code, function (err, url) {
138+
if (!err && url && typeof callback === 'function') {
139+
callback(parts.join('/') + '/live-preview.html' + '#' + url.split('#')[1]);
140+
}
141+
});
130142
}
131143
};
132144

@@ -135,7 +147,8 @@
135147
jsfiddle: launchers.jsfiddle,
136148
codepen: launchers.codepen,
137149
jsbin: launchers.jsbin,
138-
sandbox: launchers.sandbox
150+
sandbox: launchers.sandbox,
151+
liveview: launchers.liveview
139152
};
140153

141-
}(window, window.document));
154+
}(window, window.document, window.location));

lib/JSONStorage.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
+(function (window, undef) {
2+
3+
'use strict';
4+
5+
var location = window.location;
6+
var localStorage = window.localStorage;
7+
var XMLHttpRequest = window.XMLHttpRequest;
8+
9+
var proto;
10+
11+
function JSONStorage(root) {
12+
this._root = root;
13+
this._ajax = null;
14+
}
15+
16+
proto = JSONStorage.prototype;
17+
18+
proto.backup = function (data, callback) {
19+
var url = location.href.split('#')[0];
20+
localStorage.setItem(url, JSON.stringify(data));
21+
if (typeof callback === 'function') {
22+
callback(null);
23+
}
24+
};
25+
26+
proto.restore = function (callback) {
27+
var url = location.href.split('#')[0];
28+
if (typeof callback === 'function') {
29+
callback(null, localStorage[url] ? JSON.parse(localStorage[url]) : '');
30+
}
31+
};
32+
33+
proto.link = function (data, callback) {
34+
makeRequest(this, 'data', data, callback);
35+
};
36+
37+
proto.retrieve = function (key, callback) {
38+
makeRequest(this, 'key', key, callback);
39+
};
40+
41+
function makeRequest(self, name, data, callback) {
42+
if (self._ajax) {
43+
self._ajax.abort();
44+
}
45+
self._ajax = new XMLHttpRequest();
46+
self._ajax.name = name;
47+
self._ajax.onreadystatechange = handleRequest.bind(undef, self, callback);
48+
switch (name) {
49+
case 'data':
50+
self._ajax.open('POST', self._root + '.json');
51+
self._ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
52+
self._ajax.send(JSON.stringify(data));
53+
break;
54+
case 'key':
55+
self._ajax.open('GET', self._root + '/' + data + '.json');
56+
self._ajax.send();
57+
break;
58+
}
59+
}
60+
61+
function handleRequest(self, callback) {
62+
if (self._ajax.readyState === 4) {
63+
if (self._ajax.status != 200) {
64+
callback(new Error(self._ajax.status));
65+
} else {
66+
var data = self._ajax.responseText.trim();
67+
if (self._ajax.name === 'data') {
68+
data = JSON.parse(data).name;
69+
callback(null, getUrlParts() + '#' + data);
70+
} else if (self._ajax.name === 'key') {
71+
if (!data.length) {
72+
callback(new Error('Unmatched Key: ' + window.location.hash));
73+
} else {
74+
data = JSON.parse(data);
75+
callback(null, data);
76+
}
77+
}
78+
}
79+
self._ajax = null;
80+
}
81+
}
82+
83+
function getUrlParts() {
84+
return (location.protocol + '//' + location.host + location.pathname).split('/');
85+
}
86+
87+
window.JSONStorage = JSONStorage;
88+
89+
}(window));

live-preview.html

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!doctype html>
2+
<html>
3+
4+
<head>
5+
<title>HyProto Live-Preview</title>
6+
<meta charset="utf-8">
7+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
8+
<script src="lib/JSONStorage.js"></script>
9+
<style>
10+
body,
11+
html {
12+
margin: 0;
13+
padding: 0;
14+
height: 100%;
15+
overflow: hidden;
16+
}
17+
18+
#content {
19+
position: absolute;
20+
left: 0;
21+
right: 0;
22+
bottom: 0;
23+
top: 0px;
24+
}
25+
</style>
26+
</head>
27+
28+
<body>
29+
<iframe id="frame" width="100%" height="100%" frameborder="0"></iframe>
30+
<script>
31+
window.addEventListener('load', function(e) {
32+
var storage = new JSONStorage('https://glowing-fire-4998.firebaseio.com/hyproto');
33+
var frame = document.querySelector('#frame');
34+
35+
if (window.location.hash.length > 1) {
36+
storage.retrieve(window.location.hash.substring(1), function onload(err, data) {
37+
if (!err && data) {
38+
var doc = frame.contentDocument;
39+
doc.open('text/html', '');
40+
doc.write(data);
41+
doc.close();
42+
}
43+
});
44+
}
45+
});
46+
</script>
47+
</body>
48+
49+
</html>

msg/en.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var MSG = {
1212
userMenuLogout: "Logout",
1313
blocks: "Blocks",
1414
linkTooltip: "Save and Link to Blocks",
15+
qrcodeTooltip: "Generate preview QR code",
1516
runTooltip: "Run Blocks in the Workspace",
1617
badCode: "Program error:\n%1",
1718
timeout: "Maximum execution iterations exceeded.",

msg/zh-hans.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var MSG = {
1212
userMenuLogout: "登出",
1313
blocks: "积木",
1414
linkTooltip: "储存并产生连结",
15+
qrcodeTooltip: "产生即时预览 QR code",
1516
runTooltip: "执行组合",
1617
badCode: "程式错误:\n%1",
1718
timeout: "超过最大执行数",

msg/zh-hant.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var MSG = {
1212
userMenuLogout: "登出",
1313
blocks: "積木",
1414
linkTooltip: "儲存並產生連結",
15+
qrcodeTooltip: "產生即時預覽 QR code",
1516
runTooltip: "執行組合",
1617
badCode: "程式錯誤:\n%1",
1718
timeout: "超過最大執行數",

storage.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ var BlocklyStorage = {};
2929

3030
BlocklyStorage.STORAGE_URL = 'https://glowing-fire-4998.firebaseio.com';
3131

32+
BlocklyStorage.isLinkUrl = function () {
33+
var op = ['openModal', 'close'];
34+
return window.location.hash.length > 1 && op.indexOf(window.location.hash.substring(1)) === -1;
35+
};
36+
3237
/**
3338
* Backup code blocks to localStorage.
3439
* @param {!Blockly.WorkspaceSvg} workspace Workspace.
@@ -51,7 +56,7 @@ BlocklyStorage.backupOnUnload = function (opt_workspace) {
5156
var workspace = opt_workspace || Blockly.getMainWorkspace();
5257
window.addEventListener('unload',
5358
function () {
54-
if (!window.location.hash) {
59+
if (!BlocklyStorage.isLinkUrl()) {
5560
BlocklyStorage.backupBlocks_(workspace);
5661
}
5762
}, false);

0 commit comments

Comments
 (0)