fix no mascot at first launch

This commit is contained in:
ocogeclub 2021-02-26 20:11:24 +09:00
parent 04b5adaffb
commit e19acb4eb6
4 changed files with 527 additions and 523 deletions

18
package-lock.json generated
View File

@ -775,9 +775,9 @@
} }
}, },
"electron": { "electron": {
"version": "11.2.3", "version": "11.3.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-11.2.3.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-11.3.0.tgz",
"integrity": "sha512-6yxOc42nDAptHKNlUG/vcOh2GI9x2fqp2nQbZO0/3sz2CrwsJkwR3i3oMN9XhVJaqI7GK1vSCJz0verOkWlXcQ==", "integrity": "sha512-MhdS0gok3wZBTscLBbYrOhLaQybCSAfkupazbK1dMP5c+84eVMxJE/QGohiWQkzs0tVFIJsAHyN19YKPbelNrQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",
@ -1249,9 +1249,9 @@
} }
}, },
"globalthis": { "globalthis": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
"integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1499,9 +1499,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.20", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },

View File

@ -19,7 +19,7 @@
}, },
"homepage": "https://github.com/ocogeclub/ocoge#readme", "homepage": "https://github.com/ocogeclub/ocoge#readme",
"devDependencies": { "devDependencies": {
"electron": "11.2.3", "electron": "11.3.0",
"electron-rebuild": "^2.3.4" "electron-rebuild": "^2.3.4"
}, },
"dependencies": { "dependencies": {

View File

@ -18,7 +18,7 @@ const clipboard = require('electron').clipboard;
var saveFilepath = null; var saveFilepath = null;
var wsChanged = false; var wsChanged = false;
var mascotFilePath = './img/cogechee.png'; var mascotFilePath = mascotDefPath + 'cogechee.png';
// 0で数値の桁合わせ // 0で数値の桁合わせ
// NUM=値 LEN=桁数 // NUM=値 LEN=桁数
@ -26,10 +26,10 @@ const zeroPadding = (NUM, LEN) => (Array(LEN).join('0') + NUM).slice(-LEN);
// 現在の日付時刻から workspace フォルダ内のユニークなファイルパスを作成 // 現在の日付時刻から workspace フォルダ内のユニークなファイルパスを作成
const getUniqueFilepath = () => { const getUniqueFilepath = () => {
let today = new Date(); let today = new Date();
let filename = today.getFullYear() + '-' + zeroPadding((today.getMonth() + 1), 2) + '-' + zeroPadding(today.getDate(), 2) + '-' + zeroPadding(today.getHours(), 2) + '-' + zeroPadding(today.getMinutes(), 2) + '-' + zeroPadding(today.getSeconds(), 2); let filename = today.getFullYear() + '-' + zeroPadding((today.getMonth() + 1), 2) + '-' + zeroPadding(today.getDate(), 2) + '-' + zeroPadding(today.getHours(), 2) + '-' + zeroPadding(today.getMinutes(), 2) + '-' + zeroPadding(today.getSeconds(), 2);
let filepath = path.join(defpath, filename); let filepath = path.join(defpath, filename);
return filepath; return filepath;
} }
// クリップボードにコピー // クリップボードにコピー
@ -37,7 +37,7 @@ exports.copyText = text => clipboard.writeText(text);
// リンクを外部ブラウザで開く // リンクを外部ブラウザで開く
exports.openURL = (url) => { exports.openURL = (url) => {
shell.openExternal(url); shell.openExternal(url);
} }
// タイトルバーにファイル名を表示 // タイトルバーにファイル名を表示
@ -50,23 +50,23 @@ exports.openURL = (url) => {
// saveFilepath を更新 // saveFilepath を更新
// ウィンドウタイトルバーテキストを変更 // ウィンドウタイトルバーテキストを変更
const setSaveFilepath = filepath => { const setSaveFilepath = filepath => {
let title; let title;
saveFilepath = filepath; saveFilepath = filepath;
// if (filepath) title = filepath + ' - ' + appName; // if (filepath) title = filepath + ' - ' + appName;
// else title = appName; // else title = appName;
// mainWin.setTitle(title); // mainWin.setTitle(title);
this.setWsChanged(false); this.setWsChanged(false);
} }
// ワークスペースが変更された・保存された // ワークスペースが変更された・保存された
// ウィンドウタイトルバーテキストを変更 // ウィンドウタイトルバーテキストを変更
exports.setWsChanged = changed => { exports.setWsChanged = changed => {
let title; let title;
wsChanged = changed; wsChanged = changed;
if (saveFilepath) title = saveFilepath + ' - ' + appName; if (saveFilepath) title = saveFilepath + ' - ' + appName;
else title = appName; else title = appName;
if (changed) title = '*' + title; if (changed) title = '*' + title;
mainWin.setTitle(title); mainWin.setTitle(title);
} }
// 保存ファイルプロパティを更新 // 保存ファイルプロパティを更新
@ -74,159 +74,161 @@ exports.newFile = () => setSaveFilepath(null);
// ワークスペースファイル読み込みの一連の動作のラッパ // ワークスペースファイル読み込みの一連の動作のラッパ
exports.loadWsFile = () => { exports.loadWsFile = () => {
let filepath = openFile('xml', defpath); let filepath = openFile('xml', defpath);
if (filepath.length > 0) { if (filepath.length > 0) {
if (saveFilepath === null) { if (saveFilepath === null) {
setSaveFilepath(filepath); setSaveFilepath(filepath);
} //読み込みに失敗してもsaveFilepathが更新されてしまうのはちょっと具合が悪いかも } //読み込みに失敗してもsaveFilepathが更新されてしまうのはちょっと具合が悪いかも
return readFromFile(filepath); return readFromFile(filepath);
} else { } else {
return ''; return '';
} }
} }
// その他ファイル読み込みの一連の動作のラッパ // その他ファイル読み込みの一連の動作のラッパ
exports.loadFile = ext => { exports.loadFile = ext => {
let filepath = openFile(ext, defpath); let filepath = openFile(ext, defpath);
if (filepath.length > 0) { if (filepath.length > 0) {
return readFromFile(filepath); return readFromFile(filepath);
} else { } else {
return ''; return '';
} }
} }
exports.selectMascotFile = () => { exports.selectMascotFile = () => {
return openFile('png', mascotDefPath); return openFile('png', mascotDefPath);
} }
// オープンファイルダイアログ // オープンファイルダイアログ
const openFile = (ext, dpath) => { const openFile = (ext, dpath) => {
let filter; let filter;
if (ext == 'xml') { if (ext == 'xml') {
filter = { name: 'XML - Extensible Markup Language', extensions: ['xml'] }; filter = { name: 'XML - Extensible Markup Language', extensions: ['xml'] };
} else if (ext == 'js') { } else if (ext == 'js') {
filter = { name: 'JS - JavaScript', extensions: ['js'] }; filter = { name: 'JS - JavaScript', extensions: ['js'] };
} else if (ext == 'png') { } else if (ext == 'png') {
filter = { name: 'PNG - Portable Network Graphics', extensions: ['png'] }; filter = { name: 'PNG - Portable Network Graphics', extensions: ['png'] };
} else { } else {
filter = { name: 'text file', extensions: ['txt'] }; filter = { name: 'text file', extensions: ['txt'] };
} }
let filepaths = dialog.showOpenDialogSync(mainWin, { let filepaths = dialog.showOpenDialogSync(mainWin, {
properties: ['openFile'], properties: ['openFile'],
title: 'Select a file', title: 'Select a file',
defaultPath: dpath, defaultPath: dpath,
filters: [ filters: [
filter filter
] ]
}); });
if (filepaths == undefined) { if (filepaths == undefined) {
return ''; return '';
} else { } else {
return filepaths[0]; return filepaths[0];
} }
} }
// ファイルからデータを読み込み // ファイルからデータを読み込み
const readFromFile = filepath => { const readFromFile = filepath => {
let data = ''; let data = '';
try { try {
data = fs.readFileSync(filepath, 'utf-8'); data = fs.readFileSync(filepath, 'utf-8');
} }
catch (err) { catch (err) {
console.log(err); console.log(err);
} }
return data; return data;
} }
// テキストファイル読み込み: 外部スクリプト動的読み込みに使用 // テキストファイル読み込み: 外部スクリプト動的読み込みに使用
exports.readTextFile = filepath => { exports.readTextFile = filepath => {
return readFromFile(filepath); return readFromFile(filepath);
} }
// ワークスペースファイル保存の一連の動作のラッパ // ワークスペースファイル保存の一連の動作のラッパ
exports.saveWsFile = data => { exports.saveWsFile = data => {
if (saveFilepath === null) { if (saveFilepath === null) {
let filepath = selectSaveFile('xml'); let filepath = selectSaveFile('xml');
if (filepath === undefined) { //キャンセル if (filepath === undefined) { //キャンセル
return undefined; return undefined;
} else { } else {
setSaveFilepath(filepath); setSaveFilepath(filepath);
} //これも保存が成功したら変更するようにすべきかしら } //これも保存が成功したら変更するようにすべきかしら
} else this.setWsChanged(false); } else this.setWsChanged(false);
return writeToFile(saveFilepath, data); return writeToFile(saveFilepath, data);
} }
// その他ファイル保存の一連の動作のラッパ // その他ファイル保存の一連の動作のラッパ
exports.saveFile = (data, ext) => { exports.saveFile = (data, ext) => {
let filepath = selectSaveFile(ext); let filepath = selectSaveFile(ext);
if (filepath === undefined) { //キャンセル if (filepath === undefined) { //キャンセル
return undefined; return undefined;
} }
return writeToFile(filepath, data); return writeToFile(filepath, data);
} }
// ファイル保存ダイアログ // ファイル保存ダイアログ
const selectSaveFile = ext => { const selectSaveFile = ext => {
let filter; let filter;
let defName; let defName;
if (ext == 'xml') { if (ext == 'xml') {
filter = { name: 'xml file', extensions: ['xml'] }; filter = { name: 'xml file', extensions: ['xml'] };
defName = getUniqueFilepath() + '.xml'; defName = getUniqueFilepath() + '.xml';
} else if (ext == 'js') { } else if (ext == 'js') {
filter = { name: 'javascript file', extensions: ['js'] }; filter = { name: 'javascript file', extensions: ['js'] };
// ワークスペース保存名がある場合、それをベースにファイル名の候補を決める // ワークスペース保存名がある場合、それをベースにファイル名の候補を決める
if (saveFilepath === null) { if (saveFilepath === null) {
defName = getUniqueFilepath() + '.js'; defName = getUniqueFilepath() + '.js';
} else {
let dirname = path.dirname(saveFilepath);
let basename = path.basename(saveFilepath, '.xml');
defName = path.join(dirname, basename) + '.js';
}
} else { } else {
filter = { name: 'text file', extensions: ['txt'] }; let dirname = path.dirname(saveFilepath);
let basename = path.basename(saveFilepath, '.xml');
defName = path.join(dirname, basename) + '.js';
} }
let filename = dialog.showSaveDialogSync(mainWin, { } else {
title: '保存先を決定してください', filter = { name: 'text file', extensions: ['txt'] };
defaultPath: defName, }
filters: [filter] let filename = dialog.showSaveDialogSync(mainWin, {
}); title: '保存先を決定してください',
return filename; defaultPath: defName,
filters: [filter]
});
return filename;
} }
// ファイル書き込み // ファイル書き込み
const writeToFile = (filepath, data) => { const writeToFile = (filepath, data) => {
try { try {
fs.writeFileSync(filepath, data); fs.writeFileSync(filepath, data);
return true; return true;
} }
catch (err) { catch (err) {
return false; return false;
} }
} }
// 子プロセス関連 // 子プロセス関連
let children = []; let children = [];
// 新しい子プロセスを作成し、配列に保存 // 新しい子プロセスを作成し、配列に保存
exports.addChild = (child) => { exports.addChild = (child) => {
children.push(child); children.push(child);
} }
// 全ての子プロセスを殺し、配列をクリア // 全ての子プロセスを殺し、配列をクリア
exports.killAllChildren = () => { exports.killAllChildren = () => {
children.forEach(function( child ) { children.forEach(function (child) {
child.kill(); child.kill();
}); });
children = []; children = [];
} }
// 設定(保存ファイルパスと未保存フラグ)をローカルストレージに保存 // 設定(保存ファイルパスと未保存フラグ)をローカルストレージに保存
exports.savePrefsToLS = () => { exports.savePrefsToLS = () => {
let wc = '0'; let wc = '0';
if (wsChanged) wc = '1'; if (wsChanged) wc = '1';
let o = { 'saveFilepath': saveFilepath, 'wsChanged': wc, 'mascotFilePath': mascotFilePath }; let o = { 'saveFilepath': saveFilepath, 'wsChanged': wc, 'mascotFilePath': mascotFilePath };
let s = JSON.stringify(o); let s = JSON.stringify(o);
localStorage.setItem("abrage.json", s); localStorage.setItem("ocoge.json", s);
} }
// 設定(保存ファイルパスと未保存フラグ)をローカルストレージからロード // 設定(保存ファイルパスと未保存フラグ)をローカルストレージからロード
exports.loadPrefsFromLS = () => { exports.loadPrefsFromLS = () => {
let s = localStorage.getItem("abrage.json"); let s = localStorage.getItem("ocoge.json");
if (s !== null) {
let o = JSON.parse(s); let o = JSON.parse(s);
setSaveFilepath(o.saveFilepath); setSaveFilepath(o.saveFilepath);
if (o.wsChanged == '0') this.setWsChanged(false); if (o.wsChanged == '0') this.setWsChanged(false);
else this.setWsChanged(true); else this.setWsChanged(true);
if (o.mascotFilePath) this.setMascotFilePath(o.mascotFilePath); if (o.mascotFilePath) this.setMascotFilePath(o.mascotFilePath);
}
} }
// マスコット画像パスをプロパティにセット // マスコット画像パスをプロパティにセット
@ -236,5 +238,5 @@ exports.getMascotFilePath = () => mascotFilePath;
// ファイル名にアプリケーションのドキュメントルートまでのパスをつけて返す // ファイル名にアプリケーションのドキュメントルートまでのパスをつけて返す
exports.getDocPath = filename => { exports.getDocPath = filename => {
return path.join(appDocRoot, filename); return path.join(appDocRoot, filename);
} }

View File

@ -1,5 +1,5 @@
const testfunc = () => { const testfunc = () => {
elec.openURL('http://ocoge.club'); elec.openURL('http://ocoge.club');
} }
//============ User Customize Start =============== //============ User Customize Start ===============
@ -20,48 +20,48 @@ var snippets_color = '90';
// Blockly.Msg.UGJ_SNIPPETS_HUE = 90; // Blockly.Msg.UGJ_SNIPPETS_HUE = 90;
var theme = Blockly.Theme.defineTheme('ocoge', { var theme = Blockly.Theme.defineTheme('ocoge', {
'base': Blockly.Themes.Classic, 'base': Blockly.Themes.Classic,
'startHats': true, 'startHats': true,
'componentStyles': { 'componentStyles': {
'toolboxBackgroundColour': 'aliceblue', 'toolboxBackgroundColour': 'aliceblue',
'flyoutBackgroundColour': 'lavender', 'flyoutBackgroundColour': 'lavender',
'toolboxForegroundColour': 'white', 'toolboxForegroundColour': 'white',
'flyoutForegroundColour': 'steelblue' 'flyoutForegroundColour': 'steelblue'
},
'blockStyles': {
'gpio_blocks': {
"colourPrimary": gpio_color
}, },
'blockStyles': { 'multimedia_blocks': {
'gpio_blocks': { "colourPrimary": multimedia_color
"colourPrimary": gpio_color
},
'multimedia_blocks': {
"colourPrimary": multimedia_color
},
'network_blocks': {
"colourPrimary": network_color
},
'special_blocks': {
"colourPrimary": special_color
},
'snippets_blocks': {
"colourPrimary": snippets_color
}
}, },
'categoryStyles': { 'network_blocks': {
"gpio_category": { "colourPrimary": network_color
"colour": gpio_color
},
"multimedia_category": {
"colour": multimedia_color
},
"network_category": {
"colour": network_color
},
"special_category": {
"colour": special_color
},
"snippets_category": {
"colour": snippets_color
}
}, },
'special_blocks': {
"colourPrimary": special_color
},
'snippets_blocks': {
"colourPrimary": snippets_color
}
},
'categoryStyles': {
"gpio_category": {
"colour": gpio_color
},
"multimedia_category": {
"colour": multimedia_color
},
"network_category": {
"colour": network_color
},
"special_category": {
"colour": special_color
},
"snippets_category": {
"colour": snippets_color
}
},
}); });
// Customize messages // Customize messages
@ -73,64 +73,64 @@ Blockly.Msg["TEXT_PRINT_TITLE"] = "ダイアログに %1 を表示";
// Customize Toolbox // Customize Toolbox
class CustomCategory extends Blockly.ToolboxCategory { class CustomCategory extends Blockly.ToolboxCategory {
/** Constructor for a custom category. @override */ /** Constructor for a custom category. @override */
constructor(categoryDef, toolbox, opt_parent) { constructor(categoryDef, toolbox, opt_parent) {
super(categoryDef, toolbox, opt_parent); super(categoryDef, toolbox, opt_parent);
} }
/** @override */ /** @override */
addColourBorder_(colour) { addColourBorder_(colour) {
this.rowDiv_.style.backgroundColor = colour; this.rowDiv_.style.backgroundColor = colour;
} }
/** @override */ /** @override */
setSelected(isSelected) { setSelected(isSelected) {
// We do not store the label span on the category, so use getElementsByClassName. // We do not store the label span on the category, so use getElementsByClassName.
var labelDom = this.rowDiv_.getElementsByClassName('blocklyTreeLabel')[0]; var labelDom = this.rowDiv_.getElementsByClassName('blocklyTreeLabel')[0];
if (isSelected) { if (isSelected) {
// Change the background color of the div to white. // Change the background color of the div to white.
this.rowDiv_.style.backgroundColor = 'white'; this.rowDiv_.style.backgroundColor = 'white';
// Set the colour of the text to the colour of the category. // Set the colour of the text to the colour of the category.
labelDom.style.color = this.colour_; labelDom.style.color = this.colour_;
this.iconDom_.style.color = this.colour_; this.iconDom_.style.color = this.colour_;
} else { } else {
// Set the background back to the original colour. // Set the background back to the original colour.
this.rowDiv_.style.backgroundColor = this.colour_; this.rowDiv_.style.backgroundColor = this.colour_;
// Set the text back to white. // Set the text back to white.
labelDom.style.color = 'white'; labelDom.style.color = 'white';
this.iconDom_.style.color = 'white'; this.iconDom_.style.color = 'white';
}
// This is used for accessibility purposes.
Blockly.utils.aria.setState(/** @type {!Element} */(this.htmlDiv_),
Blockly.utils.aria.State.SELECTED, isSelected);
} }
// This is used for accessibility purposes.
Blockly.utils.aria.setState(/** @type {!Element} */(this.htmlDiv_),
Blockly.utils.aria.State.SELECTED, isSelected);
}
} }
Blockly.registry.register( Blockly.registry.register(
Blockly.registry.Type.TOOLBOX_ITEM, Blockly.registry.Type.TOOLBOX_ITEM,
Blockly.ToolboxCategory.registrationName, Blockly.ToolboxCategory.registrationName,
CustomCategory, true); CustomCategory, true);
//============ User Customize End =============== //============ User Customize End ===============
//背景canvasの準備 //背景canvasの準備
const ugj_canvasBgImg = (imgSrc, x, y) => { //x,y == -1: center or middle const ugj_canvasBgImg = (imgSrc, x, y) => { //x,y == -1: center or middle
let el = document.getElementById('canvas_bg'); let el = document.getElementById('canvas_bg');
let ctx = el.getContext('2d'); let ctx = el.getContext('2d');
ctx.fillStyle = 'rgb(255,255,255)'; ctx.fillStyle = 'rgb(255,255,255)';
ctx.fillRect(0,0,480,360); ctx.fillRect(0, 0, 480, 360);
let img = new Image(); let img = new Image();
img.src = imgSrc; img.src = imgSrc;
img.onload = () => { img.onload = () => {
if (x<0) { //センタリング if (x < 0) { //センタリング
let w = img.width; let w = img.width;
if (w>=480) x=0; if (w >= 480) x = 0;
else x = Math.floor((480 - w) / 2); else x = Math.floor((480 - w) / 2);
}
if (y<0) { //縦中寄せ
let h = img.height;
if (h>=360) y=0;
else y = Math.floor((360 - h) /2);
}
ctx.drawImage(img, x, y);
} }
if (y < 0) { //縦中寄せ
let h = img.height;
if (h >= 360) y = 0;
else y = Math.floor((360 - h) / 2);
}
ctx.drawImage(img, x, y);
}
}; };
// マスコット // マスコット
// ugj_canvasBgImg("./img/mimmy.png?" + new Date().getTime()); // ミミィ // ugj_canvasBgImg("./img/mimmy.png?" + new Date().getTime()); // ミミィ
@ -145,181 +145,183 @@ ugjel_inputBox = document.getElementById('inputBox'); // 入力フィールド
// その他のプロパティ // その他のプロパティ
ugj_inputEvLstnrID = 0; // 入力フォームの動的イベントリスナの最新のID ugj_inputEvLstnrID = 0; // 入力フォームの動的イベントリスナの最新のID
ugj_sounds = (names => { // サウンドファイルのいろいろの配列の初期化 ugj_sounds = (names => { // サウンドファイルのいろいろの配列の初期化
let sounds = []; let sounds = [];
names.forEach(value => { names.forEach(value => {
let filepath = `./sounds/${value}.wav`; let filepath = `./sounds/${value}.wav`;
sounds[value] = { 'file': filepath, 'audio': new Audio(filepath) }; sounds[value] = { 'file': filepath, 'audio': new Audio(filepath) };
}); });
return sounds; return sounds;
})(['meow', 'bounce', 'type_chime', 'type_dink', 'type_tap', 'type_space', 'type_return']); // サウンドファイルのベース名のリスト })(['meow', 'bounce', 'type_chime', 'type_dink', 'type_tap', 'type_space', 'type_return']); // サウンドファイルのベース名のリスト
// メソッド // メソッド
// マスコット選択 // マスコット選択
const ugj_selectMascot = () => { const ugj_selectMascot = () => {
let fname = elec.selectMascotFile(); let fname = elec.selectMascotFile();
if (fname) { if (fname) {
ugj_canvasBgImg(fname, -1, -1); ugj_canvasBgImg(fname, -1, -1);
elec.setMascotFilePath(fname); elec.setMascotFilePath(fname);
} }
} }
// サウンド再生 - 連続再生のため、再生開始後すぐにオーディオ要素を再生成する // サウンド再生 - 連続再生のため、再生開始後すぐにオーディオ要素を再生成する
const ugj_soundPlay = soundName => { const ugj_soundPlay = soundName => {
ugj_sounds[soundName]['audio'].play(); ugj_sounds[soundName]['audio'].play();
ugj_sounds[soundName]['audio'] = new Audio(ugj_sounds[soundName]['file']); ugj_sounds[soundName]['audio'] = new Audio(ugj_sounds[soundName]['file']);
}; };
// OK,Cancel 2択のダイアログを表示 // OK,Cancel 2択のダイアログを表示
const ugj_confirm = (title, message, callback) => { const ugj_confirm = (title, message, callback) => {
CustomDialog.show(title, message, { CustomDialog.show(title, message, {
showOkay: true, showOkay: true,
onOkay: () => callback(true), onOkay: () => callback(true),
showCancel: true, showCancel: true,
onCancel: () => callback(false) onCancel: () => callback(false)
}); });
}; };
const ugj_htmlEntities = str =>// HTMLエンティティのエスケープ const ugj_htmlEntities = str =>// HTMLエンティティのエスケープ
String(str).replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');//.replace(/&/g, '&amp;').replace(/ /g, '&nbsp;'); String(str).replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');//.replace(/&/g, '&amp;').replace(/ /g, '&nbsp;');
// 新規ワークスペース // 新規ワークスペース
const ugj_newWorkspace = () => { const ugj_newWorkspace = () => {
ugj_confirm('新規ワークスペース', '保存していない内容はすべて破棄されます。よろしいですか?', okey => { ugj_confirm('新規ワークスペース', '保存していない内容はすべて破棄されます。よろしいですか?', okey => {
if (okey) { if (okey) {
workspace.clear(); workspace.clear();
elec.newFile(); elec.newFile();
} }
}); });
} }
// ワークスペースをファイルに保存・読込 // ワークスペースをファイルに保存・読込
const ugj_saveWorkspaceToFile = () => { const ugj_saveWorkspaceToFile = () => {
let xml = Blockly.Xml.workspaceToDom(workspace); let xml = Blockly.Xml.workspaceToDom(workspace);
let xml_text = Blockly.Xml.domToText(xml); let xml_text = Blockly.Xml.domToText(xml);
if (elec.saveWsFile(xml_text) === false) { if (elec.saveWsFile(xml_text) === false) {
alert('保存できませんでした。'); alert('保存できませんでした。');
} }
} }
const ugj_loadWorkspaceFromFile = () => { const ugj_loadWorkspaceFromFile = () => {
let xml_text = elec.loadWsFile(); let xml_text = elec.loadWsFile();
if (xml_text.length > 0) { if (xml_text.length > 0) {
let xml = Blockly.Xml.textToDom(xml_text); let xml = Blockly.Xml.textToDom(xml_text);
Blockly.Xml.domToWorkspace(xml, workspace); Blockly.Xml.domToWorkspace(xml, workspace);
} }
} }
// ワークスペースを別名で保存 // ワークスペースを別名で保存
const ugj_saveWorkspaceAs = () => { const ugj_saveWorkspaceAs = () => {
elec.newFile(); elec.newFile();
ugj_saveWorkspaceToFile(); ugj_saveWorkspaceToFile();
} }
// ワークスペースをローカルストレージに保存・読込 // ワークスペースをローカルストレージに保存・読込
const ugj_saveWorkspace = () => { const ugj_saveWorkspace = () => {
// Workspace // Workspace
let xml = Blockly.Xml.workspaceToDom(workspace); let xml = Blockly.Xml.workspaceToDom(workspace);
let xml_text = Blockly.Xml.domToText(xml); let xml_text = Blockly.Xml.domToText(xml);
localStorage.setItem("abrage.xml", xml_text); localStorage.setItem("ocoge.xml", xml_text);
} }
const ugj_loadWorkspace = () => { const ugj_loadWorkspace = () => {
// Workspace // Workspace
let xml_text = localStorage.getItem("abrage.xml"); let xml_text = localStorage.getItem("ocoge.xml");
if (xml_text !== null) {
if (xml_text.length != 0) { if (xml_text.length != 0) {
let xml = Blockly.Xml.textToDom(xml_text); let xml = Blockly.Xml.textToDom(xml_text);
Blockly.Xml.domToWorkspace(xml, workspace); Blockly.Xml.domToWorkspace(xml, workspace);
} }
}
} }
// ワークスペースからコードを生成して必要であれば整形処理をする // ワークスペースからコードを生成して必要であれば整形処理をする
const ugj_createCode = (args) => { const ugj_createCode = (args) => {
addAsync = args.async || false; addAsync = args.async || false;
beautify = args.beautify || false; beautify = args.beautify || false;
let code = Blockly.JavaScript.workspaceToCode(workspace); let code = Blockly.JavaScript.workspaceToCode(workspace);
// 追加モジュールのrequire // 追加モジュールのrequire
let requires = [ let requires = [
['_gpio_', false, `const pi = require('ocoge_pigpiod');\n`], ['_gpio_', false, `const pi = require('ocoge_pigpiod');\n`],
['_axios_', false, `const axios = require('axios');\n`], ['_axios_', false, `const axios = require('axios');\n`],
['_sendmail', false, `const nodemailer = require('nodemailer');\n`], ['_sendmail', false, `const nodemailer = require('nodemailer');\n`],
['_cloudspeech_', false, `const speech = require('@google-cloud/speech');\nconst recorder = require('node-record-lpcm16');\n`], ['_cloudspeech_', false, `const speech = require('@google-cloud/speech');\nconst recorder = require('node-record-lpcm16');\n`],
['_httpserver', false, `const http = require('http');\n`], ['_httpserver', false, `const http = require('http');\n`],
['_file_', false, `const fs = require('fs');\n`], ['_file_', false, `const fs = require('fs');\n`],
// ['_bme280', false, `const BME280 = require('bme280-sensor');`], // ['_bme280', false, `const BME280 = require('bme280-sensor');`],
['_dht', false, `const dht = require("node-dht-sensor").promises;`], ['_dht', false, `const dht = require("node-dht-sensor").promises;`],
['_socket_', false, `const net = require('net');`] ['_socket_', false, `const net = require('net');`]
]; ];
let blockArray = workspace.getAllBlocks(); let blockArray = workspace.getAllBlocks();
blockArray.forEach(value => { blockArray.forEach(value => {
for (var i = 0, l = requires.length; i < l; i++) {
if (value.type.indexOf(requires[i][0]) >= 0) requires[i][1] = true;
}
});
for (var i = 0, l = requires.length; i < l; i++) { for (var i = 0, l = requires.length; i < l; i++) {
if (requires[i][1]) code = requires[i][2] + code; if (value.type.indexOf(requires[i][0]) >= 0) requires[i][1] = true;
} }
});
for (var i = 0, l = requires.length; i < l; i++) {
if (requires[i][1]) code = requires[i][2] + code;
}
// await使用のため、必要に応じてコード全体をasync付き即時関数でラップ // await使用のため、必要に応じてコード全体をasync付き即時関数でラップ
if (addAsync) { if (addAsync) {
code = [ code = [
'(async () => {', '(async () => {',
code, code,
'})();' '})();'
].join('\n'); ].join('\n');
} }
// コードを綺麗に // コードを綺麗に
if (beautify) code = js_beautify(code, { indent_size: 2 }); if (beautify) code = js_beautify(code, { indent_size: 2 });
return code; return code;
} }
// ブロックスクリプト実行 // ブロックスクリプト実行
const ugj_runCode = () => { const ugj_runCode = () => {
document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
let code = ugj_createCode({ 'async': true }); let code = ugj_createCode({ 'async': true });
try { try {
eval(code); eval(code);
} catch (e) { } catch (e) {
alert(e); alert(e);
} }
} }
// JavaScriptコードをダイアログで表示・保存 // JavaScriptコードをダイアログで表示・保存
// エレメントのオブジェクトとかコールバックとか // エレメントのオブジェクトとかコールバックとか
// 色々この中で完結させてみる // 色々この中で完結させてみる
const ugj_showCode = () => { const ugj_showCode = () => {
const dialog = document.getElementById('codeDlg'); const dialog = document.getElementById('codeDlg');
const content = document.getElementById('dlgContent'); const content = document.getElementById('dlgContent');
const btn_close = document.getElementById('dlgClose'); const btn_close = document.getElementById('dlgClose');
const btn_export = document.getElementById('dlgExport'); const btn_export = document.getElementById('dlgExport');
const chkbox_cli = document.getElementById('dlgCli'); const chkbox_cli = document.getElementById('dlgCli');
let code = ugj_createCode({ 'beautify': true }); let code = ugj_createCode({ 'beautify': true });
code = ugj_htmlEntities(code); code = ugj_htmlEntities(code);
content.innerHTML = PR.prettyPrintOne(code, 'js', true); content.innerHTML = PR.prettyPrintOne(code, 'js', true);
dialog.showModal(); dialog.showModal();
const close_cb = () => { const close_cb = () => {
dialog.close(); dialog.close();
btn_close.removeEventListener('click', close_cb); btn_close.removeEventListener('click', close_cb);
btn_export.removeEventListener('click', export_cb); btn_export.removeEventListener('click', export_cb);
}
const export_cb = () => {
code = ugj_createCode({ 'async': true, 'beautify': true });
// blackboardWrite()をconsole.log()に書き換え、
// document... と ugj_... と elec... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
if (chkbox_cli.checked)
code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elec.)[^;]*;)/gm, '/* $1 */');
if (elec.saveFile(code, 'js') === false) {
alert('保存できませんでした。');
} }
const export_cb = () => { close_cb();
code = ugj_createCode({ 'async': true, 'beautify': true }); }
// blackboardWrite()をconsole.log()に書き換え、 btn_close.addEventListener('click', close_cb);
// document... と ugj_... と elec... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意) btn_export.addEventListener('click', export_cb);
if (chkbox_cli.checked)
code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elec.)[^;]*;)/gm, '/* $1 */');
if (elec.saveFile(code, 'js') === false) {
alert('保存できませんでした。');
}
close_cb();
}
btn_close.addEventListener('click', close_cb);
btn_export.addEventListener('click', export_cb);
} }
@ -327,102 +329,102 @@ const ugj_showCode = () => {
ugj_fdTimeoutID = null; ugj_fdTimeoutID = null;
ugj_fdRecentBox = null; ugj_fdRecentBox = null;
const ugj_fukidashi = (text, sec) => { const ugj_fukidashi = (text, sec) => {
// Canvas Context // Canvas Context
const context = document.getElementById('canvas').getContext('2d'); const context = document.getElementById('canvas').getContext('2d');
// 吹き出しを消去する関数 // 吹き出しを消去する関数
const clearFd = (x, y, w, h) => context.clearRect(x, y, w, h); const clearFd = (x, y, w, h) => context.clearRect(x, y, w, h);
// 前回の思い出を忘れる // 前回の思い出を忘れる
if (ugj_fdRecentBox !== null) { if (ugj_fdRecentBox !== null) {
clearFd(ugj_fdRecentBox.x, ugj_fdRecentBox.y, ugj_fdRecentBox.w, ugj_fdRecentBox.h); clearFd(ugj_fdRecentBox.x, ugj_fdRecentBox.y, ugj_fdRecentBox.w, ugj_fdRecentBox.h);
clearTimeout(ugj_fdTimeoutID); clearTimeout(ugj_fdTimeoutID);
ugj_fdRecentBox = null; ugj_fdRecentBox = null;
} }
// 基本設定 // 基本設定
let rtopX = 170; // フキダシ右上 X座標 let rtopX = 170; // フキダシ右上 X座標
let rtopY = 40; // フキダシ右上 Y座標 let rtopY = 40; // フキダシ右上 Y座標
let boxWidth = 140; let boxWidth = 140;
let padding = 5; let padding = 5;
let radius = 5;// 円弧の半径 let radius = 5;// 円弧の半径
// 吹き出しの背景色 // 吹き出しの背景色
context.fillStyle = "#b7e6ff"; context.fillStyle = "#b7e6ff";
// テキスト設定 // テキスト設定
let limitedWidth = boxWidth - (padding * 2); let limitedWidth = boxWidth - (padding * 2);
let size = 14; let size = 14;
context.font = size + "px ''"; context.font = size + "px ''";
// テキスト調整 行に分解 // テキスト調整 行に分解
let lineTextList = text.split("\n"); let lineTextList = text.split("\n");
let newLineTextList = []; let newLineTextList = [];
lineTextList.forEach((lineText) => { lineTextList.forEach((lineText) => {
if (context.measureText(lineText).width > limitedWidth) {
characterList = lineText.split("");// 1文字ずつ分割
let preLineText = "";
lineText = "";
characterList.forEach((character) => {
lineText += character;
if (context.measureText(lineText).width > limitedWidth) { if (context.measureText(lineText).width > limitedWidth) {
characterList = lineText.split("");// 1文字ずつ分割 newLineTextList.push(preLineText);
let preLineText = ""; lineText = character;
lineText = "";
characterList.forEach((character) => {
lineText += character;
if (context.measureText(lineText).width > limitedWidth) {
newLineTextList.push(preLineText);
lineText = character;
}
preLineText = lineText;
});
} }
newLineTextList.push(lineText); preLineText = lineText;
}); });
let lineLength = newLineTextList.length;
// 角丸
let width = boxWidth;// 枠の幅
let height = (size * lineLength) + (padding * 3); // 枠の高さ
let toRadianCoefficient = Math.PI / 180; // 角度からラジアンへの変換係数
// 角丸原点(左上座標)
let boxOrigin = {
"x": rtopX - width,
"y": rtopY,
} }
// 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。 newLineTextList.push(lineText);
// arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り) });
context.beginPath(); let lineLength = newLineTextList.length;
context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下
context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下
context.closePath();
context.fill();
// 矢印(ヒゲ) // 角丸
let arrow = { let width = boxWidth;// 枠の幅
"x": rtopX - width / 2 + 40, let height = (size * lineLength) + (padding * 3); // 枠の高さ
"y": rtopY + height + 10, let toRadianCoefficient = Math.PI / 180; // 角度からラジアンへの変換係数
"width": 10, // 角丸原点(左上座標)
"height": 10, let boxOrigin = {
} "x": rtopX - width,
context.beginPath(); "y": rtopY,
context.moveTo(arrow.x, arrow.y); }
context.lineTo(arrow.x, arrow.y - arrow.height); // 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。
context.lineTo(arrow.x - arrow.width, arrow.y - arrow.height); // arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り)
context.fill(); context.beginPath();
context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下
context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下
context.closePath();
context.fill();
// テキスト描画 // 矢印(ヒゲ)
context.fillStyle = "#000000"; let arrow = {
newLineTextList.forEach((lineText, index) => { "x": rtopX - width / 2 + 40,
context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1))); "y": rtopY + height + 10,
}); "width": 10,
"height": 10,
}
context.beginPath();
context.moveTo(arrow.x, arrow.y);
context.lineTo(arrow.x, arrow.y - arrow.height);
context.lineTo(arrow.x - arrow.width, arrow.y - arrow.height);
context.fill();
// 描画した吹き出しの位置情報を保存 // テキスト描画
ugj_fdRecentBox = { x: boxOrigin.x, y: boxOrigin.y, w: width, h: height + arrow.height }; context.fillStyle = "#000000";
// 指定時間後に消去0以下で自動消去なし newLineTextList.forEach((lineText, index) => {
if (sec > 0) { context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1)));
ugj_fdTimeoutID = setTimeout(() => { });
clearFd(boxOrigin.x, boxOrigin.y, width, height + arrow.height);
}, sec * 1000);
}
// return [boxOrigin.x, boxOrigin.y, width, height+arrow.height]; // 描画した吹き出しの位置情報を保存
// https://qiita.com/horikeso/items/95595f379a8dfa63c34a ugj_fdRecentBox = { x: boxOrigin.x, y: boxOrigin.y, w: width, h: height + arrow.height };
// 指定時間後に消去0以下で自動消去なし
if (sec > 0) {
ugj_fdTimeoutID = setTimeout(() => {
clearFd(boxOrigin.x, boxOrigin.y, width, height + arrow.height);
}, sec * 1000);
}
// return [boxOrigin.x, boxOrigin.y, width, height+arrow.height];
// https://qiita.com/horikeso/items/95595f379a8dfa63c34a
} }
//===================================== //=====================================
@ -435,37 +437,37 @@ var blocklyDiv = document.getElementById('blocklyDiv');
// var workspace = Blockly.inject(blocklyDiv, // var workspace = Blockly.inject(blocklyDiv,
// {toolbox: document.getElementById('toolbox')}); // {toolbox: document.getElementById('toolbox')});
var workspace = Blockly.inject(blocklyDiv, var workspace = Blockly.inject(blocklyDiv,
{ {
toolbox: document.getElementById('toolbox'), toolbox: document.getElementById('toolbox'),
theme: theme, theme: theme,
scrollbars: true, scrollbars: true,
grid: { grid: {
spacing: 20, spacing: 20,
length: 1, length: 1,
colour: '#888',//888 colour: '#888',//888
snap: true snap: true
}, },
zoom: { startScale: 1.0, controls: true }, zoom: { startScale: 1.0, controls: true },
trashcan: true, trashcan: true,
media: './google-blockly/media/' media: './google-blockly/media/'
}); });
var onresize = function (e) { var onresize = function (e) {
// Compute the absolute coordinates and dimensions of blocklyArea. // Compute the absolute coordinates and dimensions of blocklyArea.
var element = blocklyArea; var element = blocklyArea;
var x = 0; var x = 0;
var y = 0; var y = 0;
do { do {
x += element.offsetLeft; x += element.offsetLeft;
y += element.offsetTop; y += element.offsetTop;
element = element.offsetParent; element = element.offsetParent;
} while (element); } while (element);
// Position blocklyDiv over blocklyArea. // Position blocklyDiv over blocklyArea.
blocklyDiv.style.left = x + 'px'; blocklyDiv.style.left = x + 'px';
blocklyDiv.style.top = y + 'px'; blocklyDiv.style.top = y + 'px';
blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
Blockly.svgResize(workspace); Blockly.svgResize(workspace);
}; };
window.addEventListener('resize', onresize, false); window.addEventListener('resize', onresize, false);
onresize(); onresize();
@ -476,95 +478,95 @@ Blockly.svgResize(workspace);
// ワークスペースの未保存の変更のフラグ // ワークスペースの未保存の変更のフラグ
const ugj_wsUpdateCB = event => { const ugj_wsUpdateCB = event => {
if (event.type != Blockly.Events.UI) { if (event.type != Blockly.Events.UI) {
elec.setWsChanged(true); elec.setWsChanged(true);
} }
} }
// ウィンドウロード・アンロード時 // ウィンドウロード・アンロード時
window.onload = () => { window.onload = () => {
var menu = document.getElementById('conmenu'); //独自コンテキストメニュー var menu = document.getElementById('conmenu'); //独自コンテキストメニュー
var area = document.getElementById('dlgContent'); //対象エリア var area = document.getElementById('dlgContent'); //対象エリア
var body = document.body; //bodyエリア var body = document.body; //bodyエリア
body.oncontextmenu = () => false; body.oncontextmenu = () => false;
//右クリック時に独自コンテキストメニューを表示する //右クリック時に独自コンテキストメニューを表示する
area.addEventListener('contextmenu', function (e) { area.addEventListener('contextmenu', function (e) {
menu.style.left = e.pageX + 'px'; menu.style.left = e.pageX + 'px';
menu.style.top = e.pageY + 'px'; menu.style.top = e.pageY + 'px';
menu.classList.add('on'); menu.classList.add('on');
}); });
//左クリック時に独自コンテキストメニューを非表示にする //左クリック時に独自コンテキストメニューを非表示にする
body.addEventListener('click', function () { body.addEventListener('click', function () {
if (menu.classList.contains('on')) { if (menu.classList.contains('on')) {
menu.classList.remove('on'); menu.classList.remove('on');
} }
}); });
// ワークスペースといくつかの環境のオートリストア // ワークスペースといくつかの環境のオートリストア
ugj_loadWorkspace(); ugj_loadWorkspace();
elec.loadPrefsFromLS(); elec.loadPrefsFromLS();
setTimeout(() => { // 環境設定のロードが終わってからイベントリスナを作成 setTimeout(() => { // 環境設定のロードが終わってからイベントリスナを作成
workspace.addChangeListener(ugj_wsUpdateCB); workspace.addChangeListener(ugj_wsUpdateCB);
}, 100); }, 100);
// 背景canvas // 背景canvas
ugj_canvasBgImg(elec.getMascotFilePath(), -1,-1); ugj_canvasBgImg(elec.getMascotFilePath(), -1, -1);
} }
window.onbeforeunload = () => { window.onbeforeunload = () => {
ugj_saveWorkspace(); ugj_saveWorkspace();
elec.savePrefsToLS(); elec.savePrefsToLS();
} }
// Electron動作とブラウザ動作を自動で仕分け // Electron動作とブラウザ動作を自動で仕分け
if (typeof require == 'function') { if (typeof require == 'function') {
// requireが使える = Electron // requireが使える = Electron
var elec = require('./scripts/eleclib'); var elec = require('./scripts/eleclib');
console.log('elec loaded.'); console.log('elec loaded.');
} else { } else {
//ブラウザ動作 //ブラウザ動作
//requireのダミー //requireのダミー
var require = (e) => { var require = (e) => {
alert(`この機能またはブロック [${e}] は web 版ではご利用になれません。\n詳しくはお問い合わせください。`); alert(`この機能またはブロック [${e}] は web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
// if (e=='elec' || e=='ocoge' || e=='child_process' || e=='@google-cloud/speech' || e=='nodemailer' || e=='fs' ) // if (e=='elec' || e=='ocoge' || e=='child_process' || e=='@google-cloud/speech' || e=='nodemailer' || e=='fs' )
// alert(`この機能またはブロックは web 版ではご利用になれません。\n詳しくはお問い合わせください。`); // alert(`この機能またはブロックは web 版ではご利用になれません。\n詳しくはお問い合わせください。`);
// else return; // else return;
} }
//elecを名前空間で置き換え //elecを名前空間で置き換え
var elec = {}; var elec = {};
elec.saveFile = () => require('elec'); elec.saveFile = () => require('elec');
elec.savePrefsToLS = () => { ; } elec.savePrefsToLS = () => { ; }
elec.loadPrefsFromLS = () => { ; } elec.loadPrefsFromLS = () => { ; }
elec.newFile = () => { ; } elec.newFile = () => { ; }
elec.setWsChanged = () => { ; } elec.setWsChanged = () => { ; }
// マスコット // マスコット
elec.getMascotFilePath = () => './img/cogechee.png'; elec.getMascotFilePath = () => './img/cogechee.png';
//ワークスペースのダウンロード //ワークスペースのダウンロード
elec.saveWsFile = xml_text => { elec.saveWsFile = xml_text => {
let blob = new Blob([xml_text], { "type": "text/xml" }); let blob = new Blob([xml_text], { "type": "text/xml" });
const downLoadLink = document.createElement("a"); const downLoadLink = document.createElement("a");
document.body.appendChild(downLoadLink); document.body.appendChild(downLoadLink);
downLoadLink.download = 'workspace.xml'; downLoadLink.download = 'workspace.xml';
downLoadLink.href = URL.createObjectURL(blob); downLoadLink.href = URL.createObjectURL(blob);
downLoadLink.click(); downLoadLink.click();
downLoadLink.parentElement.removeChild(downLoadLink); downLoadLink.parentElement.removeChild(downLoadLink);
return true; return true;
} }
//ワークスペースのインポート //ワークスペースのインポート
elec.loadWsFile = () => { elec.loadWsFile = () => {
const fileInputEl = document.createElement('input'); const fileInputEl = document.createElement('input');
document.body.appendChild(fileInputEl); document.body.appendChild(fileInputEl);
fileInputEl.type = 'file'; fileInputEl.type = 'file';
fileInputEl.addEventListener('change', ev => { fileInputEl.addEventListener('change', ev => {
let reader = new FileReader(); let reader = new FileReader();
reader.readAsText(ev.target.files[0]); reader.readAsText(ev.target.files[0]);
reader.addEventListener('load', () => { reader.addEventListener('load', () => {
let xml = Blockly.Xml.textToDom(reader.result); let xml = Blockly.Xml.textToDom(reader.result);
Blockly.Xml.domToWorkspace(xml, workspace); Blockly.Xml.domToWorkspace(xml, workspace);
}); });
}); });
fileInputEl.click(); fileInputEl.click();
fileInputEl.parentElement.removeChild(fileInputEl); fileInputEl.parentElement.removeChild(fileInputEl);
return ''; return '';
} }
} }