| | const workspace = Blockly.inject(`blocklyDiv`, { |
| | toolbox: document.getElementById(`toolbox`), |
| | renderer: `zelos`, |
| | move: { wheel: true }, |
| | zoom: { |
| | controls: true, |
| | startScale: 0.7, |
| | maxScale: 3, |
| | minScale: 0.3, |
| | scaleSpeed: 1.2, |
| | pinch: true |
| | }, |
| | grid: { |
| | spacing: 40, |
| | length: 3, |
| | colour: '#ccc', |
| | snap: true |
| | }, |
| | trashcan: false, |
| | ADD_START_HATS: true, |
| | theme: Blockly.Theme.defineTheme('mmm', { |
| | 'blockStyles': { |
| | 'motion': { |
| | 'colourPrimary': `#5597fc`, |
| | 'colourSecondary': `#3b73ca` |
| | }, |
| | 'looks': { |
| | 'colourPrimary': `#9a65fc`, |
| | 'colourSecondary': `#784cc9` |
| | }, |
| | 'sound': { |
| | 'colourPrimary': `#ce62cd`, |
| | 'colourSecondary': `#bb40bb` |
| | }, |
| | 'events': { |
| | 'colourPrimary': `#fcbf29`, |
| | 'colourSecondary': `#ca991f` |
| | }, |
| | 'control': { |
| | 'colourPrimary': `#fcaa2f`, |
| | 'colourSecondary': `#cd8a27` |
| | }, |
| | 'sensing': { |
| | 'colourPrimary': `#62b1d4`, |
| | 'colourSecondary': `#388eb6` |
| | }, |
| | 'operators': { |
| | 'colourPrimary': `#5dc05d`, |
| | 'colourSecondary': `#3c943c` |
| | }, |
| | 'variables': { |
| | 'colourPrimary': `#fc8b2d`, |
| | 'colourSecondary': `#d86d1b` |
| | }, |
| | 'data': { |
| | 'colourPrimary': `#fb642a`, |
| | 'colourSecondary': `#e34b1a` |
| | } |
| | }, |
| | 'componentStyles': { |
| | 'workspaceBackgroundColour': `#f9f9f9`, |
| | 'toolboxBackgroundColour': `#ffffff`, |
| | 'toolboxForegroundColour': `6f6f6f`, |
| | 'flyoutBackgroundColour': `#f9f9f9` |
| | }, |
| | 'startHats': true |
| | }) |
| | }); |
| |
|
| | workspace.registerButtonCallback(`createVar`, Button => { |
| | Blockly.Variables.createVariableButtonHandler(Button.getTargetWorkspace(), null, ``); |
| | }); |
| |
|
| | const style = document.getElementsByTagName(`style`)[0]; |
| | style.textContent = style.textContent.replace(/\.blocklyText/g, ``); |
| |
|
| |
|
| | const sideBtns = (document.getElementsByClassName(`sideBtn`)); |
| | const cosBtn = (document.getElementById(`cosBtn`)); |
| | const coses = (document.getElementById(`costumes`)); |
| |
|
| | let costumes = []; |
| |
|
| | const reloadCos = () => { |
| | [...coses.childNodes].forEach(v => { if (v.nodeName == `DIV`) v.remove() }); |
| | for (let i = 0; i < costumes.length; i++) { |
| | const div = document.createElement(`div`); |
| | const div2 = document.createElement(`div`); |
| | const div3 = document.createElement(`div`); |
| | const img = document.createElement(`img`); |
| | div.classList.add(`cos`); |
| | div2.textContent = i + 1; |
| | img.src = costumes[i]; |
| | div3.appendChild(img); |
| | div.append(div2, div3); |
| | div.addEventListener(`click`, () => { |
| | if (confirm(`Are you sure you want to delete it?`)) { |
| | costumes.splice(costumes.indexOf(div.childNodes[1].childNodes[0].src), 1); |
| | reloadCos(); |
| | } |
| | }); |
| | coses.appendChild(div); |
| | } |
| | } |
| |
|
| | const addCos = () => { |
| | const file = document.createElement(`input`); |
| | file.accept = `.png`; |
| | file.type = `file`; |
| | file.click(); |
| | file.addEventListener(`change`, () => { |
| | const fileReader = new FileReader(); |
| | fileReader.addEventListener(`load`, () => { |
| | costumes.push(fileReader.result); |
| | reloadCos(); |
| | }); |
| | fileReader.readAsDataURL(file.files[0]); |
| | }); |
| | } |
| |
|
| | const sb3 = async () => { |
| | fetch(`/api/check`) |
| | .then(res => res.text()) |
| | .then(resData => { |
| | if (resData == `"ok"`) { |
| | fetch(`/api/sb3`, { |
| | method: `POST`, |
| | headers: { 'Content-Type': 'application/json' }, |
| | body: JSON.stringify({ text: JSON.stringify([Blockly.JavaScript.workspaceToCode(workspace).split('$')[1], ...costumes]) }) |
| | }) |
| | .then(data => data.json()) |
| | .then(sb3Base64 => { |
| | const sb3Data = Uint8Array.from(atob(sb3Base64), c => c.charCodeAt(0)); |
| |
|
| | const a = document.createElement('a'); |
| | a.href = URL.createObjectURL(new Blob([sb3Data], { type: 'application/x-scratch-project' })); |
| | a.download = 'project.sb3'; |
| | a.click(); |
| | }); |
| | } else alert(`.sb3 There is a user currently outputting, please wait a while before pressing`); |
| | }) |
| | }; |
| |
|
| | const save = async () => { |
| | fetch(`/api/save`, { |
| | method: `POST`, |
| | headers: { 'Content-Type': 'application/json' }, |
| | body: JSON.stringify({ text: JSON.stringify([Blockly.Xml.domToText(Blockly.Xml.workspaceToDom(workspace)), Blockly.JavaScript.workspaceToCode(workspace), ...costumes]) }) |
| | }) |
| | .then(data => data.json()) |
| | .then(base64Zip => { |
| | const zipData = Uint8Array.from(atob(base64Zip), c => c.charCodeAt(0)); |
| |
|
| | const a = document.createElement(`a`); |
| | a.href = URL.createObjectURL(new Blob([zipData], { type: `application/zip` })); |
| | a.download = `project.mf4`; |
| | a.click(); |
| | }); |
| | }; |
| |
|
| | const load = async () => { |
| | const file = document.createElement(`input`); |
| | file.type = `file`; |
| | file.accept = `.mf4`; |
| | file.click(); |
| | file.addEventListener(`change`, async () => { |
| | const fileReader = new FileReader(); |
| | fileReader.addEventListener(`load`, async () => { |
| | const base64Data = btoa(String.fromCharCode.apply(null, new Uint8Array(fileReader.result))); |
| | fetch(`/api/load`, { |
| | method: `post`, |
| | headers: { 'Content-Type': 'application/json' }, |
| | body: JSON.stringify({ text: base64Data }) |
| | }) |
| | .then(res => res.json()) |
| | .then(data => { |
| | const dom = (new DOMParser()).parseFromString(data[0], `application/xml`); |
| | workspace.clear(); |
| | Blockly.Xml.domToWorkspace(dom.documentElement, workspace); |
| | costumes = data.slice(2, data.length); |
| | reloadCos(); |
| | }); |
| | }); |
| | fileReader.readAsArrayBuffer(file.files[0]); |
| | }); |
| | } |
| |
|
| | cosBtn.addEventListener(`click`, addCos); |
| | sideBtns[0].addEventListener(`click`, sb3); |
| | sideBtns[1].addEventListener(`click`, save); |
| | sideBtns[2].addEventListener(`click`, load); |