Modularize remaining objects with static methods

This commit is contained in:
Tim Mickel 2016-01-21 15:10:18 -05:00
parent 55d8b40691
commit bf07d98ccd
15 changed files with 5662 additions and 5463 deletions

View file

@ -1,33 +1,56 @@
var BlockSpecs = function () {}; import Localization from '../../utils/Localization';
import IO from '../../iPad/IO';
BlockSpecs.loadCount = 0; let loadCount = 0;
BlockSpecs.loadassets = {};
BlockSpecs.fontwhite = '#f2f3f2';
BlockSpecs.fontpink = '#ff8ae9';
BlockSpecs.fontdarkgray = '#6d6e6c';
BlockSpecs.fontblack = '#1b2a34';
BlockSpecs.fontyellow = '#ffdd33';
BlockSpecs.fontdarkgreen = '#287f46';
BlockSpecs.fontpurple = '#8f56e3';
BlockSpecs.fontblue = '#0d50ab';
BlockSpecs.fontred = '#c4281b';
BlockSpecs.fontorange = '#da8540';
BlockSpecs.fontcolors = [BlockSpecs.fontred, BlockSpecs.fontorange, BlockSpecs.fontyellow, let loadassets = {};
BlockSpecs.fontdarkgreen, BlockSpecs.fontblue, BlockSpecs.fontpink, BlockSpecs.fontpurple, let fontwhite = '#f2f3f2';
BlockSpecs.fontwhite, BlockSpecs.fontdarkgray, BlockSpecs.fontblack]; let fontpink = '#ff8ae9';
let fontdarkgray = '#6d6e6c';
let fontblack = '#1b2a34';
let fontyellow = '#ffdd33';
let fontdarkgreen = '#287f46';
let fontpurple = '#8f56e3';
let fontblue = '#0d50ab';
let fontred = '#c4281b';
let fontorange = '#da8540';
BlockSpecs.fontsizes = [16, 24, 36, 48, 56, 72]; let fontcolors = [fontred, fontorange, fontyellow,
fontdarkgreen, fontblue, fontpink, fontpurple,
fontwhite, fontdarkgray, fontblack];
BlockSpecs.getshapes = ['LetterGet_Orange', 'LetterGet_Red', 'LetterGet_Yellow', 'LetterGet_Green', let fontsizes = [16, 24, 36, 48, 56, 72];
let getshapes = ['LetterGet_Orange', 'LetterGet_Red', 'LetterGet_Yellow', 'LetterGet_Green',
'LetterGet_Blue', 'LetterGet_Purple']; 'LetterGet_Blue', 'LetterGet_Purple'];
BlockSpecs.sendshapes = ['LetterSend_Orange', 'LetterSend_Red', 'LetterSend_Yellow', 'LetterSend_Green', let sendshapes = ['LetterSend_Orange', 'LetterSend_Red', 'LetterSend_Yellow', 'LetterSend_Green',
'LetterSend_Blue', 'LetterSend_Purple']; 'LetterSend_Blue', 'LetterSend_Purple'];
BlockSpecs.speeds = ['speed0', 'speed1', 'speed2']; let speeds = ['speed0', 'speed1', 'speed2'];
BlockSpecs.initBlocks = function () { export default class BlockSpecs {
BlockSpecs.loadassets = new Object(); static get loadCount () {
return loadCount;
}
static set loadCount (newLoadCount) {
loadCount = newLoadCount;
}
static get fontcolors () {
return fontcolors;
}
static get fontsizes () {
return fontsizes;
}
static get speeds () {
return speeds;
}
static initBlocks () {
loadassets = new Object();
BlockSpecs.loadGraphics(); BlockSpecs.loadGraphics();
BlockSpecs.defs = BlockSpecs.setupBlocksSpecs(); BlockSpecs.defs = BlockSpecs.setupBlocksSpecs();
BlockSpecs.palettes = BlockSpecs.setupPalettesDef(); BlockSpecs.palettes = BlockSpecs.setupPalettesDef();
@ -41,16 +64,16 @@ BlockSpecs.initBlocks = function () {
BlockSpecs.projectThumb = BlockSpecs.getImageFrom('assets/lobby/pmask'); BlockSpecs.projectThumb = BlockSpecs.getImageFrom('assets/lobby/pmask');
} }
IO.requestFromServer('assets/balloon.svg', BlockSpecs.setBalloon); IO.requestFromServer('assets/balloon.svg', BlockSpecs.setBalloon);
BlockSpecs.loadCount++; loadCount++;
}; }
BlockSpecs.setBalloon = function (str) { static setBalloon (str) {
BlockSpecs.loadCount--; loadCount--;
BlockSpecs.balloon = str; BlockSpecs.balloon = str;
}; }
BlockSpecs.loadGraphics = function () { static loadGraphics () {
BlockSpecs.mic = BlockSpecs.getImageFrom('assets/ui/recordslot', 'svg'); BlockSpecs.mic = BlockSpecs.getImageFrom('assets/ui/recordslot', 'svg');
BlockSpecs.yellowStart = BlockSpecs.getImageFrom('assets/blocks/start', 'svg'); BlockSpecs.yellowStart = BlockSpecs.getImageFrom('assets/blocks/start', 'svg');
BlockSpecs.yellowStartH = BlockSpecs.getImageFrom('assets/blocks/eh/startH'); BlockSpecs.yellowStartH = BlockSpecs.getImageFrom('assets/blocks/eh/startH');
@ -90,32 +113,32 @@ BlockSpecs.loadGraphics = function () {
BlockSpecs.endLongS = BlockSpecs.getImageFrom('assets/blocks/shadowEndLong', 'svg'); BlockSpecs.endLongS = BlockSpecs.getImageFrom('assets/blocks/shadowEndLong', 'svg');
BlockSpecs.repeatS = BlockSpecs.getImageFrom('assets/blocks/shadowRepeat'); BlockSpecs.repeatS = BlockSpecs.getImageFrom('assets/blocks/shadowRepeat');
}; }
BlockSpecs.getImageFrom = function (url, ext) { static getImageFrom (url, ext) {
var img = document.createElement('img'); var img = document.createElement('img');
img.src = url + (ext ? '.' + ext : '.png'); img.src = url + (ext ? '.' + ext : '.png');
if (!img.complete) { if (!img.complete) {
BlockSpecs.loadassets[img.src] = img; loadassets[img.src] = img;
BlockSpecs.loadCount++; loadCount++;
img.onload = function () { img.onload = function () {
delete BlockSpecs.loadassets[img.src]; delete loadassets[img.src];
BlockSpecs.loadCount--; loadCount--;
}; };
} }
return img; return img;
}; }
BlockSpecs.refreshLoading = function () { static refreshLoading () {
for (var key in BlockSpecs.loadassets) { for (var key in loadassets) {
if (BlockSpecs.loadassets[key].complete) { if (loadassets[key].complete) {
BlockSpecs.loadCount--; loadCount--;
}
} }
} }
};
BlockSpecs.setupCategories = function () { static setupCategories () {
return new Array( return new Array(
[ [
BlockSpecs.getImageFrom('assets/categories/StartOn', 'svg'), BlockSpecs.getImageFrom('assets/categories/StartOn', 'svg'),
@ -148,46 +171,46 @@ BlockSpecs.setupCategories = function () {
Settings.categoryStopColor Settings.categoryStopColor
] ]
); );
}; }
BlockSpecs.setupPalettesDef = function () { static setupPalettesDef () {
return [['onflag', 'onclick', 'ontouch', 'onmessage', 'message'], return [['onflag', 'onclick', 'ontouch', 'onmessage', 'message'],
['forward', 'back', 'up', 'down', 'right', 'left', 'hop', 'home'], ['forward', 'back', 'up', 'down', 'right', 'left', 'hop', 'home'],
['say', 'space', 'grow', 'shrink', 'same', 'space', 'hide', 'show'], ['say', 'space', 'grow', 'shrink', 'same', 'space', 'hide', 'show'],
[], [],
['wait', 'stopmine', 'setspeed', 'repeat'], ['wait', 'stopmine', 'setspeed', 'repeat'],
['endstack', 'forever']]; ['endstack', 'forever']];
}; }
/////////////////////////////// ///////////////////////////////
// Data Structure // Data Structure
// //
// name - blocktype, icon or datastructure, blockshape, argtype, initial value, highlight, min, max, shadow // name - blocktype, icon or datastructure, blockshape, argtype, initial value, highlight, min, max, shadow
// //
// arg types: // arg types:
// null // null
// n -> number field; // n -> number field;
// t -> text field // t -> text field
// m --> image menu with argvalue equal to name; // m --> image menu with argvalue equal to name;
// d --> image menu with argvalue equal to number; // d --> image menu with argvalue equal to number;
// c -- > color drop down // c -- > color drop down
// s --> sound name // s --> sound name
// p --> page icon // p --> page icon
// //
//////////////////////////////// ////////////////////////////////
BlockSpecs.setupBlocksSpecs = function () { static setupBlocksSpecs () {
return { return {
'onflag': ['onflag', BlockSpecs.getImageFrom('assets/blockicons/greenFlag', 'svg'), 'onflag': ['onflag', BlockSpecs.getImageFrom('assets/blockicons/greenFlag', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS], BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onmessage': ['onmessage', BlockSpecs.getshapes, BlockSpecs.yellowStart, 'm', 'Orange', 'onmessage': ['onmessage', getshapes, BlockSpecs.yellowStart, 'm', 'Orange',
BlockSpecs.yellowStartH, null, null, BlockSpecs.startS], BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'onclick': ['onclick', BlockSpecs.getImageFrom('assets/blockicons/OnTouch', 'svg'), 'onclick': ['onclick', BlockSpecs.getImageFrom('assets/blockicons/OnTouch', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS], BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'ontouch': ['ontouch', BlockSpecs.getImageFrom('assets/blockicons/Bump', 'svg'), 'ontouch': ['ontouch', BlockSpecs.getImageFrom('assets/blockicons/Bump', 'svg'),
BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS], BlockSpecs.yellowStart, null, null, BlockSpecs.yellowStartH, null, null, BlockSpecs.startS],
'message': ['message', BlockSpecs.sendshapes, BlockSpecs.yellowCmd, 'm', 'Orange', 'message': ['message', sendshapes, BlockSpecs.yellowCmd, 'm', 'Orange',
BlockSpecs.yellowCmdH, null, null, BlockSpecs.cmdS], BlockSpecs.yellowCmdH, null, null, BlockSpecs.cmdS],
'repeat': ['repeat', BlockSpecs.getImageFrom('assets/blockicons/Repeat', 'svg'), 'repeat': ['repeat', BlockSpecs.getImageFrom('assets/blockicons/Repeat', 'svg'),
@ -213,7 +236,7 @@ BlockSpecs.setupBlocksSpecs = function () {
'wait': ['wait', BlockSpecs.getImageFrom('assets/blockicons/Wait', 'svg'), 'wait': ['wait', BlockSpecs.getImageFrom('assets/blockicons/Wait', 'svg'),
BlockSpecs.orangeCmd, 'n', 10, BlockSpecs.orangeCmdH, 0, 50, BlockSpecs.cmdS], BlockSpecs.orangeCmd, 'n', 10, BlockSpecs.orangeCmdH, 0, 50, BlockSpecs.cmdS],
'setspeed': ['setspeed', BlockSpecs.speeds, BlockSpecs.orangeCmd, 'd', 1, 'setspeed': ['setspeed', speeds, BlockSpecs.orangeCmd, 'd', 1,
BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS], BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
'stopmine': ['stopmine', BlockSpecs.getImageFrom('assets/blockicons/Stop', 'svg'), 'stopmine': ['stopmine', BlockSpecs.getImageFrom('assets/blockicons/Stop', 'svg'),
BlockSpecs.orangeCmd, null, null, BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS], BlockSpecs.orangeCmd, null, null, BlockSpecs.orangeCmdH, null, null, BlockSpecs.cmdS],
@ -236,7 +259,8 @@ BlockSpecs.setupBlocksSpecs = function () {
BlockSpecs.limeCmd, 's', 'pop.mp3', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS], BlockSpecs.limeCmd, 's', 'pop.mp3', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'playusersnd': ['playusersnd', BlockSpecs.getImageFrom('assets/blockicons/Microphone', 'svg'), 'playusersnd': ['playusersnd', BlockSpecs.getImageFrom('assets/blockicons/Microphone', 'svg'),
BlockSpecs.limeCmd, 'r', '1', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS], BlockSpecs.limeCmd, 'r', '1', BlockSpecs.limeCmdH, null, null, BlockSpecs.cmdS],
'endstack': ['endstack', null, BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS], 'endstack': ['endstack', null, BlockSpecs.redEnd, null, null,
BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'forever': ['forever', BlockSpecs.getImageFrom('assets/blockicons/Forever', 'svg'), 'forever': ['forever', BlockSpecs.getImageFrom('assets/blockicons/Forever', 'svg'),
BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS], BlockSpecs.redEnd, null, null, BlockSpecs.redEndH, null, null, BlockSpecs.endS],
'gotopage': ['gotopage', null, 'gotopage': ['gotopage', null,
@ -251,9 +275,9 @@ BlockSpecs.setupBlocksSpecs = function () {
BlockSpecs.getImageFrom('assets/blocks/caretcmd', 'svg'), null, null, null, null, null] BlockSpecs.getImageFrom('assets/blocks/caretcmd', 'svg'), null, null, null, null, null]
}; };
}; }
BlockSpecs.blockDesc = function (b, spr) { static blockDesc (b, spr) {
var str = b.getArgValue() ? b.getArgValue().toString() : (b.blocktype == 'playsnd') ? 'SOUND' : ''; var str = b.getArgValue() ? b.getArgValue().toString() : (b.blocktype == 'playsnd') ? 'SOUND' : '';
return { return {
@ -303,4 +327,5 @@ BlockSpecs.blockDesc = function (b, spr) {
COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE') COLOR: Localization.localize('BLOCK_DESC_MESSAGE_COLOR_ORANGE')
}) })
}; };
}; }
}

View file

@ -1,8 +1,19 @@
var Menu = function () {}; import BlockSpecs from './BlockSpecs';
import {scaleMultiplier, setProps, setCanvasSize, newHTML, isTablet,
newDiv, getDocumentHeight, drawThumbnail, frame, globalx, globaly} from '../../utils/lib';
Menu.openMenu = undefined; let openMenu = undefined;
Menu.openDropDown = function (b, fcn) { export default class Menu {
static get openMenu () {
return openMenu;
}
static set openMenu (newOpenMenu) {
openMenu = newOpenMenu;
}
static openDropDown (b, fcn) {
var size = 50; var size = 50;
var color = b.owner.blocktype == 'setspeed' ? 'orange' : 'yellow'; var color = b.owner.blocktype == 'setspeed' ? 'orange' : 'yellow';
var list = JSON.parse(b.owner.arg.list); var list = JSON.parse(b.owner.arg.list);
@ -36,10 +47,10 @@ Menu.openDropDown = function (b, fcn) {
for (var i = 0; i < list.length; i++) { for (var i = 0; i < list.length; i++) {
Menu.addImageToDropDown(mu, list[i], b, fcn); Menu.addImageToDropDown(mu, list[i], b, fcn);
} }
Menu.openMenu = mu; openMenu = mu;
}; }
Menu.addImageToDropDown = function (mu, c, block, fcn) { static addImageToDropDown (mu, c, block, fcn) {
var img = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg'); var img = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
var cs = newHTML('div', 'ddchoice', mu); var cs = newHTML('div', 'ddchoice', mu);
var micon = newHTML('canvas', undefined, cs); var micon = newHTML('canvas', undefined, cs);
@ -81,12 +92,13 @@ Menu.addImageToDropDown = function (mu, c, block, fcn) {
e.stopPropagation(); e.stopPropagation();
fcn(e, mu, block, c); fcn(e, mu, block, c);
} }
}; }
Menu.closeMyOpenMenu = function () { static closeMyOpenMenu () {
if (!Menu.openMenu) { if (!openMenu) {
return; return;
} }
Menu.openMenu.parentNode.removeChild(Menu.openMenu); openMenu.parentNode.removeChild(openMenu);
Menu.openMenu = undefined; openMenu = undefined;
}; }
}

View file

@ -1,11 +1,18 @@
var Prims = function () {}; import ScratchJr from '../ScratchJr';
import ScratchAudio from '../../utils/ScratchAudio';
import Grid from '../ui/Grid';
import Vector from '../../geom/Vector';
import {gn} from '../../utils/lib';
Prims.tinterval = 1; let tinterval = 1;
Prims.hopList = [-48, -30, -22, -14, -6, 0, 6, 14, 22, 30, 48]; let hopList = [-48, -30, -22, -14, -6, 0, 6, 14, 22, 30, 48];
Prims.soundTime = undefined;
Prims.time = 0;
Prims.init = function () { export default class Prims {
static get hopList () {
return hopList;
}
static init () {
Prims.table = {}; Prims.table = {};
Prims.table.done = Prims.Done; Prims.table.done = Prims.Done;
Prims.table.missing = Prims.Ignore; Prims.table.missing = Prims.Ignore;
@ -46,35 +53,35 @@ Prims.init = function () {
Prims.table.shrink = Prims.Shrink; Prims.table.shrink = Prims.Shrink;
Prims.table.same = Prims.Same; Prims.table.same = Prims.Same;
Prims.table.say = Prims.Say; Prims.table.say = Prims.Say;
}; }
Prims.Done = function (strip) { static Done (strip) {
if (strip.oldblock != null) { if (strip.oldblock != null) {
strip.oldblock.unhighlight(); strip.oldblock.unhighlight();
} }
strip.oldblock = null; strip.oldblock = null;
strip.isRunning = false; strip.isRunning = false;
}; }
Prims.setTime = function (strip) { static setTime (strip) {
strip.time = (new Date()) - 0; strip.time = (new Date()) - 0;
}; }
Prims.showTime = function () { static showTime () {
//var time = ((new Date()) - strip.time) / 1000; //var time = ((new Date()) - strip.time) / 1000;
// ScratchJr.log (strip.thisblock.blocktype, time, "sec") ; // ScratchJr.log (strip.thisblock.blocktype, time, "sec") ;
}; }
Prims.DoNextBlock = function (strip) { static DoNextBlock (strip) {
strip.waitTimer = Prims.tinterval * 10; strip.waitTimer = tinterval * 10;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
}; }
Prims.StopAll = function () { static StopAll () {
ScratchJr.stopStrips(); ScratchJr.stopStrips();
}; }
Prims.StopMine = function (strip) { static StopMine (strip) {
var spr = strip.spr; var spr = strip.spr;
for (var i = 0; i < ScratchJr.runtime.threadsRunning.length; i++) { for (var i = 0; i < ScratchJr.runtime.threadsRunning.length; i++) {
if ((ScratchJr.runtime.threadsRunning[i].spr == spr) if ((ScratchJr.runtime.threadsRunning[i].spr == spr)
@ -84,9 +91,9 @@ Prims.StopMine = function (strip) {
} }
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
ScratchJr.runtime.yield = true; ScratchJr.runtime.yield = true;
}; }
Prims.playSound = function (strip) { static playSound (strip) {
var b = strip.thisblock; var b = strip.thisblock;
var name = b.getSoundName(strip.spr.sounds); var name = b.getSoundName(strip.spr.sounds);
// console.log ('playSound', name); // console.log ('playSound', name);
@ -105,10 +112,10 @@ Prims.playSound = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.audio = undefined; strip.audio = undefined;
} }
strip.waitTimer = Prims.tinterval * 4; strip.waitTimer = tinterval * 4;
}; }
Prims.Say = function (strip) { static Say (strip) {
var b = strip.thisblock; var b = strip.thisblock;
var s = strip.spr; var s = strip.spr;
var str = b.getArgValue(); var str = b.getArgValue();
@ -125,13 +132,13 @@ Prims.Say = function (strip) {
Prims.showTime(strip); Prims.showTime(strip);
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = count; strip.count = count;
} }
} }
}; }
Prims.GotoPage = function (strip) { static GotoPage (strip) {
var b = strip.thisblock; var b = strip.thisblock;
var n = Number(b.getArgValue()); var n = Number(b.getArgValue());
if (strip.count < 0) { if (strip.count < 0) {
@ -145,18 +152,18 @@ Prims.GotoPage = function (strip) {
Prims.showTime(strip); Prims.showTime(strip);
ScratchJr.stage.gotoPage(n); ScratchJr.stage.gotoPage(n);
} else { } else {
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = count; strip.count = count;
} }
} }
}; }
Prims.Forever = function (strip) { static Forever (strip) {
strip.thisblock = strip.firstBlock.aStart ? strip.firstBlock.next : strip.firstBlock; strip.thisblock = strip.firstBlock.aStart ? strip.firstBlock.next : strip.firstBlock;
ScratchJr.runtime.yield = true; ScratchJr.runtime.yield = true;
}; }
Prims.Repeat = function (strip) { static Repeat (strip) {
var b = strip.thisblock; var b = strip.thisblock;
var n = Number(b.getArgValue()); var n = Number(b.getArgValue());
if (n < 1) { if (n < 1) {
@ -168,50 +175,50 @@ Prims.Repeat = function (strip) {
if (b.repeatCounter == 0) { if (b.repeatCounter == 0) {
b.repeatCounter = -1; b.repeatCounter = -1;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
} else { } else {
strip.stack.push(strip.thisblock); strip.stack.push(strip.thisblock);
b.repeatCounter--; b.repeatCounter--;
strip.thisblock = strip.thisblock.inside; strip.thisblock = strip.thisblock.inside;
ScratchJr.runtime.yield = true; ScratchJr.runtime.yield = true;
} }
}; }
Prims.Ignore = function (strip) { static Ignore (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
}; }
Prims.Wait = function (strip) { static Wait (strip) {
var n = strip.thisblock.getArgValue(); var n = strip.thisblock.getArgValue();
strip.waitTimer = Math.round(n * 3.125); // thenth of a second strip.waitTimer = Math.round(n * 3.125); // thenth of a second
Prims.setTime(strip); Prims.setTime(strip);
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
}; }
Prims.Home = function (strip) { static Home (strip) {
var spr = strip.spr; var spr = strip.spr;
spr.goHome(); spr.goHome();
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
}; }
Prims.SetSpeed = function (strip) { static SetSpeed (strip) {
var s = strip.spr; var s = strip.spr;
var num = Number(strip.thisblock.getArgValue()); // 0 - 1 - 2 var num = Number(strip.thisblock.getArgValue()); // 0 - 1 - 2
s.speed = Math.pow(2, num); s.speed = Math.pow(2, num);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
}; }
Prims.Hop = function (strip) { static Hop (strip) {
if (strip.count < 0) { // setup the hop if (strip.count < 0) { // setup the hop
strip.count = Prims.hopList.length; strip.count = hopList.length;
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.hopTo(strip); Prims.hopTo(strip);
}; }
Prims.hopTo = function (strip) { static hopTo (strip) {
var s = strip.spr; var s = strip.spr;
var b = strip.thisblock; var b = strip.thisblock;
var n = Number(b.getArgValue()); var n = Number(b.getArgValue());
@ -228,7 +235,7 @@ Prims.hopTo = function (strip) {
} else { } else {
strip.vector = { strip.vector = {
x: 0, x: 0,
y: Prims.hopList[count] y: hopList[count]
}; };
var dy = s.ycoor - strip.vector.y / 5 * n; var dy = s.ycoor - strip.vector.y / 5 * n;
if (dy < 0) { if (dy < 0) {
@ -238,17 +245,17 @@ Prims.hopTo = function (strip) {
dy = (360 - Grid.size); dy = (360 - Grid.size);
} }
s.setPos(s.xcoor + strip.vector.x, dy); s.setPos(s.xcoor + strip.vector.x, dy);
strip.waitTimer = Prims.tinterval + Math.floor(Math.pow(2, 2 - Math.floor(s.speed / 2)) / 2); strip.waitTimer = tinterval + Math.floor(Math.pow(2, 2 - Math.floor(s.speed / 2)) / 2);
strip.count = count; strip.count = count;
} }
}; }
Prims.Down = function (strip) { static Down (strip) {
var num = Number(strip.thisblock.getArgValue()) * 24; var num = Number(strip.thisblock.getArgValue()) * 24;
var distance = Math.abs(num); var distance = Math.abs(num);
if (num == 0) { if (num == 0) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.distance = -1; strip.distance = -1;
strip.vector = { strip.vector = {
x: 0, x: 0,
@ -267,14 +274,14 @@ Prims.Down = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.moveAtSpeed(strip); Prims.moveAtSpeed(strip);
}; }
Prims.Up = function (strip) { static Up (strip) {
var num = Number(strip.thisblock.getArgValue()) * 24; var num = Number(strip.thisblock.getArgValue()) * 24;
var distance = Math.abs(num); var distance = Math.abs(num);
if (num == 0) { if (num == 0) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.distance = -1; strip.distance = -1;
strip.vector = { strip.vector = {
x: 0, x: 0,
@ -290,9 +297,9 @@ Prims.Up = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.moveAtSpeed(strip); Prims.moveAtSpeed(strip);
}; }
Prims.Forward = function (strip) { static Forward (strip) {
var s = strip.spr; var s = strip.spr;
var num = Number(strip.thisblock.getArgValue()) * 24; var num = Number(strip.thisblock.getArgValue()) * 24;
var distance = Math.abs(num); var distance = Math.abs(num);
@ -302,7 +309,7 @@ Prims.Forward = function (strip) {
} }
if (num == 0) { if (num == 0) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.waitTimer = Prims.tinterval * Math.pow(2, 2 - Math.floor(s.speed / 2)); strip.waitTimer = tinterval * Math.pow(2, 2 - Math.floor(s.speed / 2));
strip.vector = { strip.vector = {
x: 0, x: 0,
y: 0 y: 0
@ -318,9 +325,9 @@ Prims.Forward = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.moveAtSpeed(strip); Prims.moveAtSpeed(strip);
}; }
Prims.Back = function (strip) { static Back (strip) {
var s = strip.spr; var s = strip.spr;
var num = Number(strip.thisblock.getArgValue()) * 24; var num = Number(strip.thisblock.getArgValue()) * 24;
var distance = Math.abs(num); var distance = Math.abs(num);
@ -334,7 +341,7 @@ Prims.Back = function (strip) {
x: 0, x: 0,
y: 0 y: 0
}; };
strip.waitTimer = Prims.tinterval * Math.pow(2, 2 - Math.floor(s.speed / 2)); strip.waitTimer = tinterval * Math.pow(2, 2 - Math.floor(s.speed / 2));
return; return;
} }
if (num == 0) { if (num == 0) {
@ -348,9 +355,9 @@ Prims.Back = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.moveAtSpeed(strip); Prims.moveAtSpeed(strip);
}; }
Prims.moveAtSpeed = function (strip) { static moveAtSpeed (strip) {
var s = strip.spr; var s = strip.spr;
var distance = strip.distance; var distance = strip.distance;
var num = Number(strip.thisblock.getArgValue()) * 12; // 1/2 cell size since vector is double var num = Number(strip.thisblock.getArgValue()) * 12; // 1/2 cell size since vector is double
@ -368,12 +375,12 @@ Prims.moveAtSpeed = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y); s.setPos(s.xcoor + vector.x, s.ycoor + vector.y);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.distance = distance; strip.distance = distance;
} }
}; }
Prims.Right = function (strip) { static Right (strip) {
var s = strip.spr; var s = strip.spr;
var num = Number(strip.thisblock.getArgValue()) * 30; var num = Number(strip.thisblock.getArgValue()) * 30;
if (strip.count < 0) { if (strip.count < 0) {
@ -390,9 +397,9 @@ Prims.Right = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.turning(strip); Prims.turning(strip);
}; }
Prims.Left = function (strip) { static Left (strip) {
var s = strip.spr; var s = strip.spr;
var num = Number(strip.thisblock.getArgValue()) * 30; var num = Number(strip.thisblock.getArgValue()) * 30;
if (strip.count < 0) { if (strip.count < 0) {
@ -409,9 +416,9 @@ Prims.Left = function (strip) {
Prims.setTime(strip); Prims.setTime(strip);
} }
Prims.turning(strip); Prims.turning(strip);
}; }
Prims.turning = function (strip) { static turning (strip) {
var s = strip.spr; var s = strip.spr;
var count = strip.count; var count = strip.count;
count--; count--;
@ -422,16 +429,16 @@ Prims.turning = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
s.setHeading(s.angle + strip.angleStep); s.setHeading(s.angle + strip.angleStep);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = count; strip.count = count;
} }
}; }
Prims.Same = function (strip) { static Same (strip) {
var s = strip.spr; var s = strip.spr;
var n = (s.defaultScale - s.scale) / s.defaultScale * 10; var n = (s.defaultScale - s.scale) / s.defaultScale * 10;
if (n == 0) { if (n == 0) {
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.count = -1; strip.count = -1;
strip.distance = -1; strip.distance = -1;
@ -456,12 +463,12 @@ Prims.Same = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
s.changeSizeBy(strip.distance * 2); s.changeSizeBy(strip.distance * 2);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = strip.count - 1; strip.count = strip.count - 1;
} }
}; }
Prims.Grow = function (strip) { static Grow (strip) {
var s = strip.spr; var s = strip.spr;
var n = Number(strip.thisblock.getArgValue()); var n = Number(strip.thisblock.getArgValue());
if (strip.count < 0) { if (strip.count < 0) {
@ -481,12 +488,12 @@ Prims.Grow = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
s.changeSizeBy(s.defaultScale * 2 * s.speed * Math.abs(n) / n); s.changeSizeBy(s.defaultScale * 2 * s.speed * Math.abs(n) / n);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = strip.count - 1; strip.count = strip.count - 1;
} }
}; }
Prims.Shrink = function (strip) { static Shrink (strip) {
var s = strip.spr; var s = strip.spr;
var n = Number(strip.thisblock.getArgValue()); var n = Number(strip.thisblock.getArgValue());
if (strip.count < 0) { if (strip.count < 0) {
@ -506,12 +513,12 @@ Prims.Shrink = function (strip) {
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} else { } else {
s.changeSizeBy(-s.defaultScale * 2 * s.speed * Math.abs(n) / n); s.changeSizeBy(-s.defaultScale * 2 * s.speed * Math.abs(n) / n);
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
strip.count = strip.count - 1; strip.count = strip.count - 1;
} }
}; }
Prims.Show = function (strip) { static Show (strip) {
var s = strip.spr; var s = strip.spr;
s.shown = true; s.shown = true;
if (strip.count < 0) { if (strip.count < 0) {
@ -528,12 +535,12 @@ Prims.Show = function (strip) {
} }
} else { } else {
s.div.style.opacity = Math.min(1, Number(s.div.style.opacity) + (s.speed / 15)); s.div.style.opacity = Math.min(1, Number(s.div.style.opacity) + (s.speed / 15));
strip.waitTimer = Prims.tinterval * 2; strip.waitTimer = tinterval * 2;
strip.count = strip.count - 1; strip.count = strip.count - 1;
} }
}; }
Prims.Hide = function (strip) { // same static Hide (strip) { // same
var s = strip.spr; var s = strip.spr;
s.shown = false; s.shown = false;
if (strip.count < 0) { if (strip.count < 0) {
@ -550,21 +557,21 @@ Prims.Hide = function (strip) { // same
} }
} else { } else {
s.div.style.opacity = Math.max(0, Number(s.div.style.opacity) - (s.speed / 15)); s.div.style.opacity = Math.max(0, Number(s.div.style.opacity) - (s.speed / 15));
strip.waitTimer = Prims.tinterval * 2; strip.waitTimer = tinterval * 2;
strip.count = strip.count - 1; strip.count = strip.count - 1;
} }
}; }
Prims.OnTouch = function (strip) { static OnTouch (strip) {
var s = strip.spr; var s = strip.spr;
if (s.touchingAny()) { if (s.touchingAny()) {
strip.stack.push(strip.firstBlock); strip.stack.push(strip.firstBlock);
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
} }
strip.waitTimer = Prims.tinterval; strip.waitTimer = tinterval;
}; }
Prims.Message = function (strip) { static Message (strip) {
var b = strip.thisblock; var b = strip.thisblock;
var pair; var pair;
if (strip.firstTime) { if (strip.firstTime) {
@ -597,13 +604,13 @@ Prims.Message = function (strip) {
strip.called = null; strip.called = null;
strip.firstTime = true; strip.firstTime = true;
strip.thisblock = strip.thisblock.next; strip.thisblock = strip.thisblock.next;
strip.waitTimer = Prims.tinterval * 2; strip.waitTimer = tinterval * 2;
} else { } else {
ScratchJr.runtime.yield = true; ScratchJr.runtime.yield = true;
} }
}; }
Prims.applyToAllStrips = function (list, fcn) { static applyToAllStrips (list, fcn) {
if (!ScratchJr.stage) { if (!ScratchJr.stage) {
return; return;
} }
@ -628,4 +635,5 @@ Prims.applyToAllStrips = function (list, fcn) {
fcn(topblocks[j], spr); fcn(topblocks[j], spr);
} }
} }
}; }
}

View file

@ -863,7 +863,6 @@ Sprite.prototype.activateInput = function () {
var ti = document.forms.activetextbox.typing; var ti = document.forms.activetextbox.typing;
gn('textbox').style.visibility = 'visible'; gn('textbox').style.visibility = 'visible';
var me = this; var me = this;
Undo.aux = Project.getProject(ScratchJr.stage.currentPage.id);
ti.onblur = function () { ti.onblur = function () {
me.unfocusText(); me.unfocusText();
}; };

View file

@ -1,17 +1,24 @@
var Alert = function () {}; import DrawPath from '../../utils/DrawPath';
import {globalx, globaly, scaleMultiplier, newCanvas,
setCanvasSize, setProps, writeText, getStringSize} from '../../utils/lib';
Alert.balloon = undefined; let balloon = undefined;
Alert.close = function () { export default class Alert {
if (!Alert.balloon) { static get balloon () {
return balloon;
}
static close () {
if (!balloon) {
return; return;
} }
Alert.balloon.parentNode.removeChild(Alert.balloon); balloon.parentNode.removeChild(balloon);
Alert.balloon = undefined; balloon = undefined;
}; }
Alert.open = function (p, obj, label, color) { static open (p, obj, label, color) {
if (Alert.balloon) { if (balloon) {
Alert.close(); Alert.close();
} }
var scale = scaleMultiplier; var scale = scaleMultiplier;
@ -23,12 +30,12 @@ Alert.open = function (p, obj, label, color) {
dy = 5 * scale; dy = 5 * scale;
} }
Alert.balloon = newCanvas(p, dx, dy, w, h, { balloon = newCanvas(p, dx, dy, w, h, {
position: 'absolute', position: 'absolute',
zIndex: 2 zIndex: 2
}); });
Alert.balloon.icon = obj; balloon.icon = obj;
var ctx = Alert.balloon.getContext('2d'); var ctx = balloon.getContext('2d');
w = 16 + getStringSize(ctx, 'bold 14px Verdana', label).width; w = 16 + getStringSize(ctx, 'bold 14px Verdana', label).width;
if (w < 36) { if (w < 36) {
w = 36; w = 36;
@ -38,8 +45,8 @@ Alert.open = function (p, obj, label, color) {
dx = 5 * scale; dx = 5 * scale;
} }
dx = Math.floor(dx); dx = Math.floor(dx);
setCanvasSize(Alert.balloon, w, 36); setCanvasSize(balloon, w, 36);
setProps(Alert.balloon.style, { setProps(balloon.style, {
position: 'absolute', position: 'absolute',
left: dx + 'px', left: dx + 'px',
zIndex: 1000, zIndex: 1000,
@ -47,11 +54,11 @@ Alert.open = function (p, obj, label, color) {
'scale(' + scale + ', ' + scale + ') ' + 'scale(' + scale + ', ' + scale + ') ' +
'translate(' + (w / 2) + 'px, ' + (h / 2) + 'px) ' 'translate(' + (w / 2) + 'px, ' + (h / 2) + 'px) '
}); });
Alert.draw(Alert.balloon.getContext('2d'), 6, w, h, color); Alert.draw(balloon.getContext('2d'), 6, w, h, color);
writeText(ctx, 'bold 14px Verdana', 'white', label, 20, 8); writeText(ctx, 'bold 14px Verdana', 'white', label, 20, 8);
}; }
Alert.draw = function (ctx, curve, w, h, color) { static draw (ctx, curve, w, h, color) {
curve = 10; curve = 10;
var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2], var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2],
['q', curve, 0, curve, curve], ['v', h - curve * 2], ['q', 0, curve, -curve, curve], ['q', curve, 0, curve, curve], ['v', h - curve * 2], ['q', 0, curve, -curve, curve],
@ -63,4 +70,5 @@ Alert.draw = function (ctx, curve, w, h, color) {
ctx.beginPath(); ctx.beginPath();
DrawPath.render(ctx, path); DrawPath.render(ctx, path);
ctx.fill(); ctx.fill();
}; }
}

View file

@ -2,39 +2,50 @@
// Stage grid // Stage grid
////////////////////////////// //////////////////////////////
var Grid = function () {}; import ScratchJr from '../ScratchJr';
import Events from '../../utils/Events';
import Localization from '../../utils/Localization';
import {gn, scaleMultiplier, isTablet, newDiv, setProps, newP, newCanvas} from '../../utils/lib';
Grid.width = 482; let width = 482;
Grid.height = 362; let height = 362;
Grid.size = 24; let size = 24;
let hidden = true;
Grid.hidden = true; export default class Grid {
static get size () {
return size;
}
Grid.init = function (div) { static get hidden () {
return hidden;
}
static init (div) {
var w = div.offsetWidth; var w = div.offsetWidth;
var h = div.offsetHeight; var h = div.offsetHeight;
var grid = newDiv(div, 0, 0, Grid.width, Grid.height, { var grid = newDiv(div, 0, 0, width, height, {
position: 'absolute', position: 'absolute',
zIndex: ScratchJr.layerTop zIndex: ScratchJr.layerTop
}); });
Grid.setScaleAndPosition(grid, scaleMultiplier, 47, 75, Grid.width, Grid.height); Grid.setScaleAndPosition(grid, scaleMultiplier, 47, 75, width, height);
grid.setAttribute('id', 'livegrid'); grid.setAttribute('id', 'livegrid');
Grid.drawLines(grid, Grid.width, Grid.height); Grid.drawLines(grid, width, height);
Grid.createNumbering(w, h); Grid.createNumbering(w, h);
Grid.createCursor(); Grid.createCursor();
Grid.createYcursor(); Grid.createYcursor();
Grid.createXcursor(); Grid.createXcursor();
}; }
Grid.setScaleAndPosition = function (grid, scale, x, y, w, h) { static setScaleAndPosition (grid, scale, x, y, w, h) {
setProps(grid.style, { setProps(grid.style, {
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' + webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + scale + ') ' + 'scale(' + scale + ') ' +
'translate(' + (w / 2 + x) + 'px, ' + (h / 2 + y) + 'px)' 'translate(' + (w / 2 + x) + 'px, ' + (h / 2 + y) + 'px)'
}); });
}; }
Grid.drawLines = function (grid, w, h) { static drawLines (grid, w, h) {
var cnv = newCanvas(grid, 0, 0, w, h, { var cnv = newCanvas(grid, 0, 0, w, h, {
position: 'absolute' position: 'absolute'
}); });
@ -42,21 +53,21 @@ Grid.drawLines = function (grid, w, h) {
var ctx = cnv.getContext('2d'); var ctx = cnv.getContext('2d');
ctx.strokeStyle = '#B3B3B3'; ctx.strokeStyle = '#B3B3B3';
ctx.lineWidth = 1; ctx.lineWidth = 1;
var dx = Grid.size; var dx = size;
// vertical // vertical
for (var i = 0; i < 480 / Grid.size; i++) { for (var i = 0; i < 480 / size; i++) {
ctx.moveTo(dx, 0); ctx.moveTo(dx, 0);
ctx.lineTo(dx, 360); ctx.lineTo(dx, 360);
ctx.stroke(); ctx.stroke();
dx += Grid.size; dx += size;
} }
var dy = Grid.size; var dy = size;
// horizontal // horizontal
for (i = 0; i < 360 / Grid.size; i++) { for (i = 0; i < 360 / size; i++) {
ctx.moveTo(0, dy); ctx.moveTo(0, dy);
ctx.lineTo(480, dy); ctx.lineTo(480, dy);
ctx.stroke(); ctx.stroke();
dy += Grid.size; dy += size;
} }
if (isTablet) { if (isTablet) {
cnv.ontouchstart = function (evt) { cnv.ontouchstart = function (evt) {
@ -67,19 +78,19 @@ Grid.drawLines = function (grid, w, h) {
ScratchJr.stage.mouseDown(evt); ScratchJr.stage.mouseDown(evt);
}; };
} }
}; }
Grid.createNumbering = function (w, h) { static createNumbering (w, h) {
var row = newDiv(gn('stageframe'), 0, 0, w - 46 - 30, 24, { var row = newDiv(gn('stageframe'), 0, 0, w - 46 - 30, 24, {
position: 'absolute', position: 'absolute',
zIndex: ScratchJr.layerTop zIndex: ScratchJr.layerTop
}); });
row.setAttribute('id', 'rownum'); row.setAttribute('id', 'rownum');
Grid.setScaleAndPosition(row, scaleMultiplier, 46 - 24, 75 + Grid.height, w - 46 - 30, 24); Grid.setScaleAndPosition(row, scaleMultiplier, 46 - 24, 75 + height, w - 46 - 30, 24);
var offset = Grid.size; var offset = size;
var dx = offset; var dx = offset;
for (var i = 0; i < 480 / offset; i++) { for (var i = 0; i < 480 / offset; i++) {
var num = newDiv(row, dx, 0, Grid.size, Grid.size, { var num = newDiv(row, dx, 0, size, size, {
position: 'absolute', position: 'absolute',
zIndex: 10 zIndex: 10
}); });
@ -97,7 +108,7 @@ Grid.createNumbering = function (w, h) {
Grid.setScaleAndPosition(column, scaleMultiplier, 46 - 24, 74 + 1, 24, h + 24); Grid.setScaleAndPosition(column, scaleMultiplier, 46 - 24, 74 + 1, 24, h + 24);
var dy = 360 - offset; var dy = 360 - offset;
for (var j = 0; j < 360 / offset; j++) { for (var j = 0; j < 360 / offset; j++) {
var numj = newDiv(column, 0, dy, Grid.size, Grid.size, { var numj = newDiv(column, 0, dy, size, size, {
position: 'absolute', position: 'absolute',
zIndex: 10 zIndex: 10
}); });
@ -107,10 +118,10 @@ Grid.createNumbering = function (w, h) {
py.setAttribute('class', 'stylelabel'); py.setAttribute('class', 'stylelabel');
dy -= offset; dy -= offset;
} }
}; }
Grid.createYcursor = function () { static createYcursor () {
var num = newDiv(gn('colnum'), 0, 0, Grid.size, Grid.size, { var num = newDiv(gn('colnum'), 0, 0, size, size, {
position: 'absolute', position: 'absolute',
zIndex: 20 zIndex: 20
}); });
@ -119,10 +130,10 @@ Grid.createYcursor = function () {
num.setAttribute('id', 'ycursor'); num.setAttribute('id', 'ycursor');
var p = newP(num, 15, {}); var p = newP(num, 15, {});
p.setAttribute('class', 'circlenum'); p.setAttribute('class', 'circlenum');
}; }
Grid.createXcursor = function () { static createXcursor () {
var num = newDiv(gn('rownum'), Grid.size, 0, Grid.size, Grid.size, { var num = newDiv(gn('rownum'), size, 0, size, size, {
position: 'absolute', position: 'absolute',
zIndex: 20 zIndex: 20
}); });
@ -131,15 +142,15 @@ Grid.createXcursor = function () {
num.setAttribute('id', 'xcursor'); num.setAttribute('id', 'xcursor');
var p = newP(num, 1, {}); var p = newP(num, 1, {});
p.setAttribute('class', 'circlenum'); p.setAttribute('class', 'circlenum');
}; }
Grid.createCursor = function () { static createCursor () {
var gc = newDiv(gn('livegrid'), 0, 0, Grid.size + 2, Grid.size + 2, { var gc = newDiv(gn('livegrid'), 0, 0, size + 2, size + 2, {
position: 'absolute', position: 'absolute',
zIndex: ScratchJr.layerAboveBottom zIndex: ScratchJr.layerAboveBottom
}); });
gc.setAttribute('id', 'circlenum'); gc.setAttribute('id', 'circlenum');
var cnv = newCanvas(gc, 0, 0, Grid.size + 2, Grid.size + 2, { var cnv = newCanvas(gc, 0, 0, size + 2, size + 2, {
position: 'absolute' position: 'absolute'
}); });
if (isTablet) { if (isTablet) {
@ -156,16 +167,16 @@ Grid.createCursor = function () {
ctx.fillStyle = '#28A5DA'; ctx.fillStyle = '#28A5DA';
ctx.strokeStyle = '#656e73'; ctx.strokeStyle = '#656e73';
ctx.lineWidth = 3; ctx.lineWidth = 3;
ctx.strokeRect(3, 3, Grid.size - 6, Grid.size - 6); ctx.strokeRect(3, 3, size - 6, size - 6);
ctx.fillRect(3, 3, Grid.size - 6, Grid.size - 6); ctx.fillRect(3, 3, size - 6, size - 6);
if (isTablet) { if (isTablet) {
gc.ontouchstart = Grid.mouseDownOnCursor; gc.ontouchstart = Grid.mouseDownOnCursor;
} else { } else {
gc.onmousedown = Grid.mouseDownOnCursor; gc.onmousedown = Grid.mouseDownOnCursor;
} }
}; }
Grid.mouseDownOnCursor = function (e) { static mouseDownOnCursor (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var pt = ScratchJr.stage.getStagePt(e); var pt = ScratchJr.stage.getStagePt(e);
@ -180,10 +191,10 @@ Grid.mouseDownOnCursor = function (e) {
Events.holdit(spr.div, ScratchJr.stage.startShaking); Events.holdit(spr.div, ScratchJr.stage.startShaking);
} }
ScratchJr.stage.setEvents(); ScratchJr.stage.setEvents();
}; }
Grid.updateCursor = function () { static updateCursor () {
if (Grid.hidden) { if (hidden) {
return; return;
} }
if (ScratchJr.inFullscreen) { if (ScratchJr.inFullscreen) {
@ -207,18 +218,18 @@ Grid.updateCursor = function () {
if (!c) { if (!c) {
return; return;
} }
var dx = obj.xcoor + Grid.size / 2; var dx = obj.xcoor + size / 2;
var dy = obj.ycoor - Grid.size / 2; var dy = obj.ycoor - size / 2;
gn('xcursor').style.visibility = 'visible'; gn('xcursor').style.visibility = 'visible';
gn('ycursor').style.visibility = 'visible'; gn('ycursor').style.visibility = 'visible';
gn('circlenum').style.visibility = 'visible'; gn('circlenum').style.visibility = 'visible';
Grid.setCursorsValues(dx, dy); Grid.setCursorsValues(dx, dy);
}; }
Grid.setCursorsValues = function (dx, dy) { static setCursorsValues (dx, dy) {
var c = gn('circlenum'); var c = gn('circlenum');
var numX = Math.round(dx / Grid.size); var numX = Math.round(dx / size);
var numY = Math.round(dy / Grid.size); var numY = Math.round(dy / size);
if (c.offsetLeft != (numX * 24)) { if (c.offsetLeft != (numX * 24)) {
var xc = gn('xcursor'); var xc = gn('xcursor');
var xstate = ((numX < 1) || (numX > 20)) ? 'hidden' : 'visible'; var xstate = ((numX < 1) || (numX > 20)) ? 'hidden' : 'visible';
@ -248,11 +259,11 @@ Grid.setCursorsValues = function (dx, dy) {
top: (numY * 24) + 'px', top: (numY * 24) + 'px',
left: ((numX - 1) * 24) + 'px' left: ((numX - 1) * 24) + 'px'
}); });
}; }
Grid.hide = function (b) { static hide (b) {
Grid.hidden = b; hidden = b;
var mystate = Grid.hidden ? 'hidden' : 'visible'; var mystate = hidden ? 'hidden' : 'visible';
gn('livegrid').style.visibility = mystate; gn('livegrid').style.visibility = mystate;
gn('rownum').style.visibility = mystate; gn('rownum').style.visibility = mystate;
gn('colnum').style.visibility = mystate; gn('colnum').style.visibility = mystate;
@ -262,4 +273,5 @@ Grid.hide = function (b) {
gn('circlenum').style.visibility = mystate; gn('circlenum').style.visibility = mystate;
gn('xcursor').style.visibility = mystate; gn('xcursor').style.visibility = mystate;
gn('ycursor').style.visibility = mystate; gn('ycursor').style.visibility = mystate;
}; }
}

View file

@ -1,26 +1,27 @@
var Library = function () {};
Library.selectedOne; import ScratchJr from '../ScratchJr';
Library.currentProject; import iOS from '../../iPad/iOS';
Library.activeFocus; import IO from '../../iPad/IO';
Library.nativeJr = true; import Paint from '../../painteditor/Paint';
Library.clickThumb; import Events from '../../utils/Events';
Library.shaking; import Localization from '../../utils/Localization';
Library.type; import ScratchAudio from '../../utils/ScratchAudio';
Library.timeoutEvent; import {frame, gn, newHTML, scaleMultiplier,
Library.spacing = 64; getDocumentWidth, getDocumentHeight, setProps, newCanvas} from '../../utils/lib';
Library.fw = 220;
Library.pad;
Library.thumbnailw = 136;
Library.target = undefined;
Library.scrolltop = 0;
Library.frame;
Library.ready = false;
Library.init = function () { let selectedOne;
Library.frame = document.getElementById('libframe'); let nativeJr = true;
Library.frame.style.minHeight = Math.max(getDocumentHeight(), frame.offsetHeight) + 'px'; let clickThumb;
var topbar = newHTML('div', 'topbar', Library.frame); let shaking;
let type;
let timeoutEvent;
let frame;
export default class Library {
static init () {
frame = document.getElementById('libframe');
frame.style.minHeight = Math.max(getDocumentHeight(), frame.offsetHeight) + 'px';
var topbar = newHTML('div', 'topbar', frame);
topbar.setAttribute('id', 'topbar'); topbar.setAttribute('id', 'topbar');
var actions = newHTML('div', 'actions', topbar); var actions = newHTML('div', 'actions', topbar);
actions.setAttribute('id', 'libactions'); actions.setAttribute('id', 'libactions');
@ -30,27 +31,24 @@ Library.init = function () {
myname.setAttribute('id', 'assetname'); myname.setAttribute('id', 'assetname');
myname.textContent = ''; myname.textContent = '';
Library.layoutHeader(); Library.layoutHeader();
}; }
Library.createScrollPanel = function () { static createScrollPanel () {
var inner = newHTML('div', 'innerlibrary', Library.frame); var inner = newHTML('div', 'innerlibrary', frame);
inner.setAttribute('id', 'asssetsview'); inner.setAttribute('id', 'asssetsview');
var div = newHTML('div', 'scrollarea', inner); var div = newHTML('div', 'scrollarea', inner);
div.setAttribute('id', 'scrollarea'); div.setAttribute('id', 'scrollarea');
}; }
Library.open = function (type) { static open (type) {
Library.ready = false; type = type;
Library.type = type;
gn('assetname').textContent = ''; gn('assetname').textContent = '';
Library.nativeJr = true; nativeJr = true;
Library.target = undefined;
Library.pad = undefined;
frame.style.display = 'none'; frame.style.display = 'none';
Library.frame.className = 'libframe appear'; frame.className = 'libframe appear';
Library.frame.focus(); frame.focus();
Library.selectedOne = undefined; selectedOne = undefined;
gn('okbut').ontouchstart = (Library.type == 'costumes') ? Library.closeSpriteSelection : Library.closeBkgSelection; gn('okbut').ontouchstart = (type == 'costumes') ? Library.closeSpriteSelection : Library.closeBkgSelection;
Library.clean(); Library.clean();
Library.createScrollPanel(); Library.createScrollPanel();
Library.addThumbnails(type); Library.addThumbnails(type);
@ -68,28 +66,28 @@ Library.open = function (type) {
e.initTouchEvent(); e.initTouchEvent();
Library.cancelPick(e); Library.cancelPick(e);
}); });
}; }
Library.clean = function () { static clean () {
if (gn('scrollarea')) { if (gn('scrollarea')) {
var div = gn('scrollarea').parentNode; var div = gn('scrollarea').parentNode;
Library.frame.removeChild(div); frame.removeChild(div);
}
} }
};
Library.close = function (e) { static close (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
ScratchAudio.sndFX('tap.wav'); ScratchAudio.sndFX('tap.wav');
ScratchJr.blur(); ScratchJr.blur();
Library.frame.className = 'libframe disappear'; frame.className = 'libframe disappear';
document.body.scrollTop = 0; document.body.scrollTop = 0;
frame.style.display = 'block'; frame.style.display = 'block';
ScratchJr.editorEvents(); ScratchJr.editorEvents();
ScratchJr.onBackButtonCallback.pop(); ScratchJr.onBackButtonCallback.pop();
}; }
Library.layoutHeader = function () { static layoutHeader () {
var buttons = newHTML('div', 'bkgbuttons', gn('libactions')); var buttons = newHTML('div', 'bkgbuttons', gn('libactions'));
var paintme = newHTML('div', 'painticon', buttons); var paintme = newHTML('div', 'painticon', buttons);
paintme.id = 'library_paintme'; paintme.id = 'library_paintme';
@ -98,53 +96,52 @@ Library.layoutHeader = function () {
okbut.setAttribute('id', 'okbut'); okbut.setAttribute('id', 'okbut');
var cancelbut = newHTML('div', 'cancelicon', buttons); var cancelbut = newHTML('div', 'cancelicon', buttons);
cancelbut.ontouchstart = Library.cancelPick; cancelbut.ontouchstart = Library.cancelPick;
}; }
Library.cancelPick = function (e) { static cancelPick (e) {
ScratchJr.onHold = true; ScratchJr.onHold = true;
Library.close(e); Library.close(e);
setTimeout(function () { setTimeout(function () {
ScratchJr.onHold = false; ScratchJr.onHold = false;
}, 1000); }, 1000);
}; }
Library.addThumbnails = function () { static addThumbnails () {
var div = gn('scrollarea'); var div = gn('scrollarea');
Library.addEmptyThumb(div, (Library.type == 'costumes') ? (118 * scaleMultiplier) : (120 * scaleMultiplier), Library.addEmptyThumb(div, (type == 'costumes') ? (118 * scaleMultiplier) : (120 * scaleMultiplier),
(Library.type == 'costumes') ? (90 * scaleMultiplier) : (90 * scaleMultiplier)); (type == 'costumes') ? (90 * scaleMultiplier) : (90 * scaleMultiplier));
var key = (Library.type == 'costumes') ? 'usershapes' : 'userbkgs'; var key = (type == 'costumes') ? 'usershapes' : 'userbkgs';
// Student' assets // Student' assets
var json = {}; var json = {};
json.cond = 'ext = ? AND version = ?'; json.cond = 'ext = ? AND version = ?';
json.items = ((Library.type == 'costumes') ? json.items = ((type == 'costumes') ?
['md5', 'altmd5', 'name', 'scale', 'width', 'height'] : ['altmd5', 'md5', 'width', 'height']); ['md5', 'altmd5', 'name', 'scale', 'width', 'height'] : ['altmd5', 'md5', 'width', 'height']);
json.values = ['svg', ScratchJr.version]; json.values = ['svg', ScratchJr.version];
json.order = 'ctime desc'; json.order = 'ctime desc';
IO.query(key, json, Library.displayAssets); IO.query(key, json, Library.displayAssets);
}; }
Library.skipUserAssets = function () { static skipUserAssets () {
var div = gn('scrollarea'); var div = gn('scrollarea');
Library.addEmptyThumb(div, (Library.type == 'costumes') ? (118 * scaleMultiplier) : (120 * scaleMultiplier), Library.addEmptyThumb(div, (type == 'costumes') ? (118 * scaleMultiplier) : (120 * scaleMultiplier),
(Library.type == 'costumes') ? (90 * scaleMultiplier) : (90 * scaleMultiplier)); (type == 'costumes') ? (90 * scaleMultiplier) : (90 * scaleMultiplier));
Library.addHR(div); Library.addHR(div);
Library.displayLibAssets((Library.type == 'costumes') ? MediaLib.sprites : MediaLib.backgrounds); Library.displayLibAssets((type == 'costumes') ? MediaLib.sprites : MediaLib.backgrounds);
}; }
Library.getpadding = function (div) { static getpadding (div) {
var w = Math.min(getDocumentWidth(), Library.frame.offsetWidth); var w = Math.min(getDocumentWidth(), frame.offsetWidth);
var dw = div.childNodes[1].offsetLeft - div.childNodes[0].offsetLeft; var dw = div.childNodes[1].offsetLeft - div.childNodes[0].offsetLeft;
var qty = Math.floor(w / dw); var qty = Math.floor(w / dw);
Library.thumbnailw = dw + 10;
var pad = Math.floor((w - (qty * dw)) / 2); var pad = Math.floor((w - (qty * dw)) / 2);
if (pad < 10) { if (pad < 10) {
return Math.floor((w - ((qty - 1) * dw)) / 2); return Math.floor((w - ((qty - 1) * dw)) / 2);
} }
return pad; return pad;
}; }
Library.displayAssets = function (str) { static displayAssets (str) {
Library.nativeJr = true; nativeJr = true;
var div = gn('scrollarea'); var div = gn('scrollarea');
var data = JSON.parse(str); var data = JSON.parse(str);
if (data.length > 0) { if (data.length > 0) {
@ -154,12 +151,12 @@ Library.displayAssets = function (str) {
} }
} }
Library.addHR(div); Library.addHR(div);
Library.nativeJr = false; nativeJr = false;
data = (Library.type == 'costumes') ? MediaLib.sprites : MediaLib.backgrounds; data = (type == 'costumes') ? MediaLib.sprites : MediaLib.backgrounds;
Library.displayLibAssets(data); Library.displayLibAssets(data);
}; }
Library.displayLibAssets = function (data) { static displayLibAssets (data) {
var div = gn('scrollarea'); var div = gn('scrollarea');
if (data.length < 1) { if (data.length < 1) {
return; return;
@ -176,17 +173,17 @@ Library.displayLibAssets = function (data) {
if ('separator' in data[i]) { if ('separator' in data[i]) {
Library.addHR(div); Library.addHR(div);
} else { } else {
Library.addLocalThumbChoose(div, data[i], 120 * scaleMultiplier, 90 * scaleMultiplier, Library.selectAsset); Library.addLocalThumbChoose(div, data[i], 120 * scaleMultiplier,
90 * scaleMultiplier, Library.selectAsset);
}
} }
} }
Library.ready = true;
};
Library.addAssetThumbChoose = function (parent, aa, w, h, fcn) { static addAssetThumbChoose (parent, aa, w, h, fcn) {
var data = Library.parseAssetData(aa); var data = Library.parseAssetData(aa);
var tb = document.createElement('div'); var tb = document.createElement('div');
parent.appendChild(tb); parent.appendChild(tb);
tb.byme = Library.nativeJr ? 1 : 0; tb.byme = nativeJr ? 1 : 0;
var md5 = data.md5; var md5 = data.md5;
tb.setAttribute('class', 'assetbox off'); tb.setAttribute('class', 'assetbox off');
tb.setAttribute('id', md5); tb.setAttribute('id', md5);
@ -210,12 +207,12 @@ Library.addAssetThumbChoose = function (parent, aa, w, h, fcn) {
fcn(evt, tb); fcn(evt, tb);
}; };
return tb; return tb;
}; }
Library.addLocalThumbChoose = function (parent, data, w, h, fcn) { static addLocalThumbChoose (parent, data, w, h, fcn) {
var tb = newHTML('div', 'assetbox off', parent); var tb = newHTML('div', 'assetbox off', parent);
var md5 = data.md5; var md5 = data.md5;
tb.byme = Library.nativeJr ? 1 : 0; tb.byme = nativeJr ? 1 : 0;
tb.setAttribute('id', md5); tb.setAttribute('id', md5);
tb.scale = (!data.scale) ? 0.5 : data.scale; tb.scale = (!data.scale) ? 0.5 : data.scale;
tb.fieldname = data.name; tb.fieldname = data.name;
@ -239,9 +236,9 @@ Library.addLocalThumbChoose = function (parent, data, w, h, fcn) {
fcn(evt, tb); fcn(evt, tb);
}; };
return tb; return tb;
}; }
Library.userAssetThumbnail = function (img, cnv, sizew, sizeh) { static userAssetThumbnail (img, cnv, sizew, sizeh) {
var scale = Math.min(sizew / img.width, sizeh / img.height); var scale = Math.min(sizew / img.width, sizeh / img.height);
var currentCtx = cnv.getContext('2d'); var currentCtx = cnv.getContext('2d');
var iw = Math.floor(scale * img.width); var iw = Math.floor(scale * img.width);
@ -249,13 +246,13 @@ Library.userAssetThumbnail = function (img, cnv, sizew, sizeh) {
var ix = Math.floor((sizew - (scale * img.width)) / 2); var ix = Math.floor((sizew - (scale * img.width)) / 2);
var iy = Math.floor((sizeh - (scale * img.height)) / 2); var iy = Math.floor((sizeh - (scale * img.height)) / 2);
currentCtx.drawImage(img, 0, 0, img.width, img.height, ix, iy, iw, ih); currentCtx.drawImage(img, 0, 0, img.width, img.height, ix, iy, iw, ih);
}; }
Library.addEmptyThumb = function (parent, w, h) { static addEmptyThumb (parent, w, h) {
var tb = document.createElement('div'); var tb = document.createElement('div');
tb.setAttribute('class', 'assetbox off'); tb.setAttribute('class', 'assetbox off');
tb.setAttribute('id', 'none'); tb.setAttribute('id', 'none');
tb.fieldname = ((Library.type == 'costumes') ? tb.fieldname = ((type == 'costumes') ?
Localization.localize('LIBRARY_CHARACTER') : Localization.localize('LIBRARY_BACKGROUND')); Localization.localize('LIBRARY_CHARACTER') : Localization.localize('LIBRARY_BACKGROUND'));
tb.byme = 1; tb.byme = 1;
var cnv = newCanvas(tb, 9 * scaleMultiplier, 7 * scaleMultiplier, w, h, { var cnv = newCanvas(tb, 9 * scaleMultiplier, 7 * scaleMultiplier, w, h, {
@ -268,24 +265,24 @@ Library.addEmptyThumb = function (parent, w, h) {
tb.ontouchstart = function (evt) { tb.ontouchstart = function (evt) {
Library.selectAsset(evt, tb); Library.selectAsset(evt, tb);
}; };
}; }
Library.addHR = function (div) { static addHR (div) {
var hr = document.createElement('hr'); var hr = document.createElement('hr');
div.appendChild(hr); div.appendChild(hr);
hr.setAttribute('class', 'bigdivide'); hr.setAttribute('class', 'bigdivide');
}; }
/////////////////////////// ///////////////////////////
//selection //selection
Library.selectAsset = function (e, tb) { static selectAsset (e, tb) {
tb.pt = JSON.stringify(Events.getTargetPoint(e)); tb.pt = JSON.stringify(Events.getTargetPoint(e));
if (Library.shaking && (e.target.className == 'deleteasset')) { if (shaking && (e.target.className == 'deleteasset')) {
Library.removeFromAssetList(); Library.removeFromAssetList();
return; return;
} else if (Library.shaking) { } else if (shaking) {
Library.stopShaking(); Library.stopShaking();
} }
if (tb.byme && (tb.id != 'none')) { if (tb.byme && (tb.id != 'none')) {
@ -305,13 +302,13 @@ Library.selectAsset = function (e, tb) {
tb.ontouchend = undefined; tb.ontouchend = undefined;
window.onmouseup = undefined; window.onmouseup = undefined;
window.onmousemove = undefined; window.onmousemove = undefined;
Library.timeoutEvent = undefined; timeoutEvent = undefined;
Library.stopShaking(); Library.stopShaking();
Library.shaking = tb; shaking = tb;
Library.clearAllSelections(); Library.clearAllSelections();
Library.startShaking(tb); Library.startShaking(tb);
}; };
Library.timeoutEvent = setTimeout(repeat, 500); timeoutEvent = setTimeout(repeat, 500);
} }
function clearEvents (e, tb) { function clearEvents (e, tb) {
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
@ -320,13 +317,13 @@ Library.selectAsset = function (e, tb) {
return; return;
} }
e.preventDefault(); e.preventDefault();
if (Library.timeoutEvent) { if (timeoutEvent) {
clearTimeout(Library.timeoutEvent); clearTimeout(timeoutEvent);
} }
if (Library.clickThumb) { if (clickThumb) {
Library.unSelect(Library.clickThumb); Library.unSelect(clickThumb);
} }
Library.timeoutEvent = undefined; timeoutEvent = undefined;
tb.ontouchend = undefined; tb.ontouchend = undefined;
window.onmouseup = function () { window.onmouseup = function () {
window.onmousemove = undefined; window.onmousemove = undefined;
@ -334,57 +331,57 @@ Library.selectAsset = function (e, tb) {
}; };
} }
function clickMe (e, tb) { function clickMe (e, tb) {
if (Library.timeoutEvent) { if (timeoutEvent) {
clearTimeout(Library.timeoutEvent); clearTimeout(timeoutEvent);
} }
Library.selectThisAsset(e, tb); Library.selectThisAsset(e, tb);
Library.timeoutEvent = undefined; timeoutEvent = undefined;
tb.ontouchend = undefined; tb.ontouchend = undefined;
tb.onmouseup = undefined; tb.onmouseup = undefined;
window.onmousemove = undefined; window.onmousemove = undefined;
window.onmouseup = undefined; window.onmouseup = undefined;
} }
}; }
Library.startShaking = function (b) { static startShaking (b) {
b.className = b.className + ' shakeme'; b.className = b.className + ' shakeme';
newHTML('div', 'deleteasset', b); newHTML('div', 'deleteasset', b);
Library.shaking = b; shaking = b;
}; }
Library.stopShaking = function () { static stopShaking () {
if (!Library.shaking) { if (!shaking) {
return; return;
} }
var b = Library.shaking; var b = shaking;
b.setAttribute('class', 'assetbox off'); b.setAttribute('class', 'assetbox off');
var ic = b.childNodes[b.childElementCount - 1]; var ic = b.childNodes[b.childElementCount - 1];
if (ic.getAttribute('class') == 'deleteasset') { if (ic.getAttribute('class') == 'deleteasset') {
b.removeChild(ic); b.removeChild(ic);
} }
Library.shaking = undefined; shaking = undefined;
}; }
Library.removeFromAssetList = function () { static removeFromAssetList () {
ScratchAudio.sndFX('cut.wav'); ScratchAudio.sndFX('cut.wav');
var b = Library.shaking; var b = shaking;
b.parentNode.removeChild(b); b.parentNode.removeChild(b);
var key = (Library.type == 'costumes') ? 'usershapes' : 'userbkgs'; var key = (type == 'costumes') ? 'usershapes' : 'userbkgs';
var json = {}; var json = {};
json.cond = 'md5 = ?'; json.cond = 'md5 = ?';
json.items = ['*']; json.items = ['*'];
json.values = [b.id]; json.values = [b.id];
IO.query(key, json, Library.removeAssetFromLib); IO.query(key, json, Library.removeAssetFromLib);
Library.clickThumb = undefined; clickThumb = undefined;
Library.selectedOne = undefined; selectedOne = undefined;
return true; return true;
}; }
// Determine if an asset thumbnail is unique // Determine if an asset thumbnail is unique
// md5: thumbnail md5 to determine uniqueness // md5: thumbnail md5 to determine uniqueness
// type: "costumes" or "backgrounds" // type: "costumes" or "backgrounds"
// callback: called with true if unique, false if duplicate exists // callback: called with true if unique, false if duplicate exists
Library.assetThumbnailUnique = function (md5, type, callback) { static assetThumbnailUnique (md5, type, callback) {
var key = (type == 'costumes') ? 'usershapes' : 'userbkgs'; var key = (type == 'costumes') ? 'usershapes' : 'userbkgs';
var json = {}; var json = {};
json.cond = 'ext = ? AND altmd5 = ?'; json.cond = 'ext = ? AND altmd5 = ?';
@ -395,10 +392,10 @@ Library.assetThumbnailUnique = function (md5, type, callback) {
results = JSON.parse(results); results = JSON.parse(results);
callback(results.length <= 1); callback(results.length <= 1);
}); });
}; }
Library.removeAssetFromLib = function (str) { static removeAssetFromLib (str) {
var key = (Library.type == 'costumes') ? 'usershapes' : 'userbkgs'; var key = (type == 'costumes') ? 'usershapes' : 'userbkgs';
var aa = JSON.parse(str)[0]; var aa = JSON.parse(str)[0];
var data = Library.parseAssetData(aa); var data = Library.parseAssetData(aa);
@ -406,7 +403,7 @@ Library.removeAssetFromLib = function (str) {
// Removes the thumbnail for the asset. // Removes the thumbnail for the asset.
// First ensure that there aren't other characters/bgs using the same thumb // First ensure that there aren't other characters/bgs using the same thumb
// (this is possible if we receive a duplicate project, for example) // (this is possible if we receive a duplicate project, for example)
Library.assetThumbnailUnique(data.altmd5, Library.type, function (isUnique) { Library.assetThumbnailUnique(data.altmd5, type, function (isUnique) {
if (isUnique) { if (isUnique) {
iOS.remove(data.altmd5, iOS.trace); iOS.remove(data.altmd5, iOS.trace);
} }
@ -414,19 +411,19 @@ Library.removeAssetFromLib = function (str) {
} }
IO.deleteobject(key, data.id, iOS.trace); IO.deleteobject(key, data.id, iOS.trace);
}; }
Library.parseAssetData = function (data) { static parseAssetData (data) {
var res = new Object(); var res = new Object();
for (var key in data) { for (var key in data) {
res[key.toLowerCase()] = data[key]; res[key.toLowerCase()] = data[key];
} }
return res; return res;
}; }
Library.selectThisAsset = function (e, tb) { static selectThisAsset (e, tb) {
if (tb.id == Library.selectedOne) { if (tb.id == selectedOne) {
if (Library.type == 'costumes') { if (type == 'costumes') {
Library.closeSpriteSelection(e); Library.closeSpriteSelection(e);
} else { } else {
Library.closeBkgSelection(e); Library.closeBkgSelection(e);
@ -446,36 +443,36 @@ Library.selectThisAsset = function (e, tb) {
} }
tb.className = 'assetbox on'; tb.className = 'assetbox on';
Library.selectedOne = tb.id; selectedOne = tb.id;
Library.clickThumb = tb; clickThumb = tb;
if (tb.fieldname) { if (tb.fieldname) {
gn('assetname').textContent = tb.fieldname; gn('assetname').textContent = tb.fieldname;
} }
} }
}; }
Library.clearAllSelections = function () { static clearAllSelections () {
var div = gn('scrollarea'); var div = gn('scrollarea');
for (var i = 0; i < div.childElementCount; i++) { for (var i = 0; i < div.childElementCount; i++) {
if (div.childNodes[i].nodeName == 'DIV') { if (div.childNodes[i].nodeName == 'DIV') {
div.childNodes[i].className = 'assetbox off'; div.childNodes[i].className = 'assetbox off';
} }
} }
}; }
Library.unSelect = function (tb) { static unSelect (tb) {
gn('assetname').textContent = ''; gn('assetname').textContent = '';
tb.className = 'assetbox off'; tb.className = 'assetbox off';
Library.selectedOne = undefined; selectedOne = undefined;
if (Library.clickThumb) { if (clickThumb) {
if (tb.byme && (Library.clickThumb.childElementCount > 1)) { if (tb.byme && (clickThumb.childElementCount > 1)) {
Library.clickThumb.childNodes[Library.clickThumb.childElementCount - 1].style.visibility = 'hidden'; clickThumb.childNodes[clickThumb.childElementCount - 1].style.visibility = 'hidden';
}
clickThumb = undefined;
} }
Library.clickThumb = undefined;
} }
};
Library.resizeScroll = function () { static resizeScroll () {
var w = Math.min(getDocumentWidth(), frame.offsetWidth); var w = Math.min(getDocumentWidth(), frame.offsetWidth);
var h = Math.max(getDocumentHeight(), frame.offsetHeight); var h = Math.max(getDocumentHeight(), frame.offsetHeight);
var dx = w - 20 * scaleMultiplier; var dx = w - 20 * scaleMultiplier;
@ -483,70 +480,71 @@ Library.resizeScroll = function () {
width: dx + 'px', width: dx + 'px',
height: (h - 120 * scaleMultiplier) + 'px' height: (h - 120 * scaleMultiplier) + 'px'
}); });
}; }
/////////////////////////////////////////// ///////////////////////////////////////////
// Object actions // Object actions
////////////////////////////////////////// //////////////////////////////////////////
Library.editResource = function (e) { static editResource (e) {
Library.close(e); Library.close(e);
if (Library.type != 'costumes') { if (type != 'costumes') {
Library.editBackground(e); Library.editBackground(e);
} else { } else {
Library.editCostume(e); Library.editCostume(e);
} }
}; }
Library.editBackground = function () { static editBackground () {
var md5 = Library.selectedOne && (Library.selectedOne != 'none') ? Library.selectedOne : undefined; var md5 = selectedOne && (selectedOne != 'none') ? selectedOne : undefined;
Paint.open(true, md5); Paint.open(true, md5);
}; }
Library.editCostume = function () { static editCostume () {
var sname = undefined; var sname = undefined;
var cname = Library.selectedOne ? Library.clickThumb.fieldname : Localization.localize('LIBRARY_CHARACTER'); var cname = selectedOne ? clickThumb.fieldname : Localization.localize('LIBRARY_CHARACTER');
var scale = Library.selectedOne && (Library.selectedOne != 'none') ? Library.clickThumb.scale : 0.5; var scale = selectedOne && (selectedOne != 'none') ? clickThumb.scale : 0.5;
var md5 = Library.selectedOne && (Library.selectedOne != 'none') ? Library.selectedOne : undefined; var md5 = selectedOne && (selectedOne != 'none') ? selectedOne : undefined;
var w = Library.selectedOne && (Library.selectedOne != 'none') ? Math.round(Library.clickThumb.w) : undefined; var w = selectedOne && (selectedOne != 'none') ? Math.round(clickThumb.w) : undefined;
var h = Library.selectedOne && (Library.selectedOne != 'none') ? Math.round(Library.clickThumb.h) : undefined; var h = selectedOne && (selectedOne != 'none') ? Math.round(clickThumb.h) : undefined;
Paint.open(false, md5, sname, cname, scale, w, h); Paint.open(false, md5, sname, cname, scale, w, h);
}; }
Library.closeSpriteSelection = function (e) { static closeSpriteSelection (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var id = Library.selectedOne ? Library.clickThumb.fieldname : Localization.localize('LIBRARY_CHARACTER'); var id = selectedOne ? clickThumb.fieldname : Localization.localize('LIBRARY_CHARACTER');
if (Library.selectedOne && (Library.selectedOne != 'none')) { if (selectedOne && (selectedOne != 'none')) {
ScratchJr.stage.currentPage.addSprite(Library.clickThumb.scale, Library.selectedOne, id); ScratchJr.stage.currentPage.addSprite(clickThumb.scale, selectedOne, id);
} }
// Prevent reporting user asset names // Prevent reporting user asset names
if (Library.clickThumb) { if (clickThumb) {
var analyticsName = Library.clickThumb.fieldname; var analyticsName = clickThumb.fieldname;
if (!(Library.selectedOne in MediaLib.keys)) { if (!(selectedOne in MediaLib.keys)) {
analyticsName = 'user_asset'; analyticsName = 'user_asset';
} }
iOS.analyticsEvent('editor', 'new_character', analyticsName); iOS.analyticsEvent('editor', 'new_character', analyticsName);
} }
Library.close(e); Library.close(e);
}; }
Library.closeBkgSelection = function (e) { static closeBkgSelection (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (Library.selectedOne) { if (selectedOne) {
ScratchJr.stage.currentPage.setBackground(Library.selectedOne, ScratchJr.stage.currentPage.updateBkg); ScratchJr.stage.currentPage.setBackground(selectedOne, ScratchJr.stage.currentPage.updateBkg);
} }
Library.close(e); Library.close(e);
}; }
///////////////////////////////////////// /////////////////////////////////////////
//Key Handeling Top Level prevention //Key Handeling Top Level prevention
///////////////////////////////////////// /////////////////////////////////////////
Library.distance = function (pt1, pt2) { static distance (pt1, pt2) {
var dx = pt1.x - pt2.x; var dx = pt1.x - pt2.x;
var dy = pt1.y - pt2.y; var dy = pt1.y - pt2.y;
return Math.round(Math.sqrt((dx * dx) + (dy * dy))); return Math.round(Math.sqrt((dx * dx) + (dy * dy)));
}; }
}

View file

@ -2,22 +2,48 @@
// Blocks Categories Palettes // Blocks Categories Palettes
/////////////////////////////////// ///////////////////////////////////
Palette = function () {}; import ScratchJr from '../ScratchJr';
import Block from '../blocks/Block';
import BlockSpecs from '../blocks/BlockSpecs';
import ScriptsPane from './ScriptsPane';
import Undo from './Undo';
import iOS from '../../iPad/iOS';
import Events from '../../utils/Events';
import Rectangle from '../../geom/Rectangle';
import DrawPath from '../../utils/DrawPath';
import ScratchAudio from '../../utils/ScratchAudio';
import Record from './Record';
import {frame, gn, localx, newHTML, scaleMultiplier, isTablet, newDiv,
setProps, globalx, localy, globaly, drawScaled, newCanvas,
setCanvasSize, hitRect, writeText, getStringSize} from '../../utils/lib';
Palette.blockscale = 0.75;
Palette.numcat = 0;
Palette.betweenblocks = undefined; // Set in setup()
Palette.blockdy = 5;
Palette.timeoutid = undefined;
Palette.helpballoon = undefined;
Palette.dxblocks = 10;
Palette.currentCategory;
Palette.setup = function (parent) { let blockscale = 0.75;
Palette.blockscale *= scaleMultiplier; let numcat = 0; // getter
Palette.blockdy *= scaleMultiplier; let betweenblocks = undefined; // Set in setup()
Palette.blockdx *= scaleMultiplier; let blockdy = 5;
Palette.betweenblocks = 90 * Palette.blockscale; let timeoutid = undefined;
let helpballoon = undefined;
let dxblocks = 10;
export default class Palette {
static get numcat () {
return numcat;
}
static get helpballoon () {
return helpballoon;
}
static set helpballoon (newHelpballoon) {
helpballoon = newHelpballoon;
}
static setup (parent) {
blockscale *= scaleMultiplier;
blockdy *= scaleMultiplier;
Palette.blockdx *= scaleMultiplier; // XXX
betweenblocks = 90 * blockscale;
Palette.createCategorySelectors(parent); Palette.createCategorySelectors(parent);
var div = newHTML('div', 'palette', parent); var div = newHTML('div', 'palette', parent);
div.setAttribute('id', 'palette'); div.setAttribute('id', 'palette');
@ -26,9 +52,9 @@ Palette.setup = function (parent) {
}; };
var pc = newHTML('div', 'papercut', parent); var pc = newHTML('div', 'papercut', parent);
newHTML('div', 'withstyle', pc); newHTML('div', 'withstyle', pc);
}; }
Palette.createCategorySelectors = function (parent) { static createCategorySelectors (parent) {
var sel = newHTML('div', 'categoryselector', parent); var sel = newHTML('div', 'categoryselector', parent);
sel.setAttribute('id', 'selectors'); sel.setAttribute('id', 'selectors');
var bkg = newHTML('div', 'catbkg', sel); var bkg = newHTML('div', 'catbkg', sel);
@ -38,9 +64,9 @@ Palette.createCategorySelectors = function (parent) {
for (var i = 0; i < BlockSpecs.categories.length; i++) { for (var i = 0; i < BlockSpecs.categories.length; i++) {
Palette.createSelector(sel, i, leftPx + i * widthPx, 0, BlockSpecs.categories[i]); Palette.createSelector(sel, i, leftPx + i * widthPx, 0, BlockSpecs.categories[i]);
} }
}; }
Palette.paletteMouseDown = function (e) { static paletteMouseDown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -68,15 +94,15 @@ Palette.paletteMouseDown = function (e) {
} }
} }
ScratchJr.clearSelection(); ScratchJr.clearSelection();
}; }
Palette.isRecorded = function (ths) { static isRecorded (ths) {
var val = ths.owner.getArgValue(); var val = ths.owner.getArgValue();
var list = ScratchJr.getActiveScript().owner.spr.sounds; var list = ScratchJr.getActiveScript().owner.spr.sounds;
return list.indexOf(val) > 0; return list.indexOf(val) > 0;
}; }
Palette.removeSound = function (ths) { static removeSound (ths) {
ScratchAudio.sndFX('cut.wav'); ScratchAudio.sndFX('cut.wav');
var indx = ths.owner.getArgValue(); var indx = ths.owner.getArgValue();
var spr = ScratchJr.getSprite(); var spr = ScratchJr.getSprite();
@ -110,9 +136,9 @@ Palette.removeSound = function (ths) {
ScratchJr.storyStart('Palette.removeSound'); // Record a change for sample projects in story-starter mode ScratchJr.storyStart('Palette.removeSound'); // Record a change for sample projects in story-starter mode
Palette.selectCategory(3); Palette.selectCategory(3);
}; }
Palette.showHelp = function (e, b) { static showHelp (e, b) {
var block = b.owner; var block = b.owner;
var help = BlockSpecs.blockDesc(block, ScratchJr.getSprite()); var help = BlockSpecs.blockDesc(block, ScratchJr.getSprite());
var str = help[block.blocktype]; var str = help[block.blocktype];
@ -120,10 +146,10 @@ Palette.showHelp = function (e, b) {
return; return;
} }
Palette.openPaletteBalloon(b, str); Palette.openPaletteBalloon(b, str);
Palette.timeoutid = setTimeout(Palette.closeHelpBalloon, 2000); timeoutid = setTimeout(Palette.closeHelpBalloon, 2000);
}; }
Palette.startShaking = function (b) { static startShaking (b) {
if (!b.owner) { if (!b.owner) {
return; return;
} }
@ -134,18 +160,18 @@ Palette.startShaking = function (b) {
ScratchJr.stopShaking = Palette.stopShaking; ScratchJr.stopShaking = Palette.stopShaking;
b.setAttribute('class', 'shakeme'); b.setAttribute('class', 'shakeme');
newHTML('div', 'deletesound', b); newHTML('div', 'deletesound', b);
}; }
Palette.clickBlock = function (e, b) { static clickBlock (e, b) {
if (ScratchJr.shaking && (b == ScratchJr.shaking)) { if (ScratchJr.shaking && (b == ScratchJr.shaking)) {
Palette.removeSound(b); Palette.removeSound(b);
} else { } else {
ScratchJr.clearSelection(); ScratchJr.clearSelection();
Palette.showHelp(e, b); Palette.showHelp(e, b);
} }
}; }
Palette.stopShaking = function (b) { static stopShaking (b) {
if (!b.owner) { if (!b.owner) {
return; return;
} }
@ -156,62 +182,62 @@ Palette.stopShaking = function (b) {
if (ic.getAttribute('class') == 'deletesound') { if (ic.getAttribute('class') == 'deletesound') {
b.removeChild(ic); b.removeChild(ic);
} }
}; }
Palette.openPaletteBalloon = function (obj, label) { static openPaletteBalloon (obj, label) {
if (Palette.helpballoon) { if (helpballoon) {
Palette.closeHelpBalloon(); Palette.closeHelpBalloon();
} }
var fontSize = Math.floor(14 * window.devicePixelRatio * scaleMultiplier); var fontSize = Math.floor(14 * window.devicePixelRatio * scaleMultiplier);
var w = window.devicePixelRatio * 80 * scaleMultiplier; var w = window.devicePixelRatio * 80 * scaleMultiplier;
var h = window.devicePixelRatio * 36 * scaleMultiplier; var h = window.devicePixelRatio * 36 * scaleMultiplier;
var dy = globaly(obj) - 36 * scaleMultiplier; var dy = globaly(obj) - 36 * scaleMultiplier;
Palette.helpballoon = newCanvas(frame, 0, dy, w, h, { helpballoon = newCanvas(frame, 0, dy, w, h, {
position: 'absolute', position: 'absolute',
zIndex: 1000 zIndex: 1000
}); });
Palette.helpballoon.icon = obj; helpballoon.icon = obj;
var ctx = Palette.helpballoon.getContext('2d'); var ctx = helpballoon.getContext('2d');
w = 16 * window.devicePixelRatio * scaleMultiplier + w = 16 * window.devicePixelRatio * scaleMultiplier +
getStringSize(ctx, 'bold ' + fontSize + 'px ' + Settings.paletteBalloonFont, label).width; getStringSize(ctx, 'bold ' + fontSize + 'px ' + Settings.paletteBalloonFont, label).width;
if (w < 36 * scaleMultiplier) { if (w < 36 * scaleMultiplier) {
w = 36 * scaleMultiplier; w = 36 * scaleMultiplier;
} }
var dx = (globalx(obj) + (obj.offsetWidth / 2)) * window.devicePixelRatio - (w / 2); var dx = (globalx(obj) + (obj.offsetWidth / 2)) * window.devicePixelRatio - (w / 2);
setCanvasSize(Palette.helpballoon, w, h); setCanvasSize(helpballoon, w, h);
setProps(Palette.helpballoon.style, { setProps(helpballoon.style, {
position: 'absolute', position: 'absolute',
webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' + webkitTransform: 'translate(' + (-w / 2) + 'px, ' + (-h / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') translate(' + (dx + (w / 2)) + 'px, ' + (h / 2) + 'px)' 'scale(' + (1 / window.devicePixelRatio) + ') translate(' + (dx + (w / 2)) + 'px, ' + (h / 2) + 'px)'
}); });
Palette.drawBalloon(Palette.helpballoon.getContext('2d'), w, h); Palette.drawBalloon(helpballoon.getContext('2d'), w, h);
writeText(ctx, 'bold ' + fontSize + 'px ' + Settings.paletteBalloonFont, 'white', label, writeText(ctx, 'bold ' + fontSize + 'px ' + Settings.paletteBalloonFont, 'white', label,
21 * window.devicePixelRatio * scaleMultiplier, 8 * window.devicePixelRatio * scaleMultiplier); 21 * window.devicePixelRatio * scaleMultiplier, 8 * window.devicePixelRatio * scaleMultiplier);
}; }
Palette.hide = function () { static hide () {
gn('blockspalette').childNodes[0].style.display = 'none'; gn('blockspalette').childNodes[0].style.display = 'none';
gn('blockspalette').childNodes[1].style.display = 'none'; gn('blockspalette').childNodes[1].style.display = 'none';
}; }
Palette.show = function () { static show () {
gn('blockspalette').childNodes[0].style.display = 'inline-block'; gn('blockspalette').childNodes[0].style.display = 'inline-block';
gn('blockspalette').childNodes[1].style.display = 'inline-block'; gn('blockspalette').childNodes[1].style.display = 'inline-block';
};
Palette.closeHelpBalloon = function () {
if (Palette.timeoutid) {
clearTimeout(Palette.timeoutid);
} }
if (Palette.helpballoon) {
Palette.helpballoon.parentNode.removeChild(Palette.helpballoon);
}
Palette.helpballoon = undefined;
Palette.timeoutid = undefined;
};
Palette.drawBalloon = function (ctx, w, h) {
static closeHelpBalloon () {
if (timeoutid) {
clearTimeout(timeoutid);
}
if (helpballoon) {
helpballoon.parentNode.removeChild(helpballoon);
}
helpballoon = undefined;
timeoutid = undefined;
}
static drawBalloon (ctx, w, h) {
var curve = 4; var curve = 4;
var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2], var path = new Array(['M', 0, curve], ['q', 0, -curve, curve, -curve], ['h', w - curve * 2],
['q', curve, 0, curve, curve], ['v', h - 11 - curve * 2], ['q', 0, curve, -curve, curve], ['q', curve, 0, curve, curve], ['v', h - 11 - curve * 2], ['q', 0, curve, -curve, curve],
@ -225,10 +251,10 @@ Palette.drawBalloon = function (ctx, w, h) {
ctx.beginPath(); ctx.beginPath();
DrawPath.render(ctx, path); DrawPath.render(ctx, path);
ctx.fill(); ctx.fill();
// ctx.stroke(); // ctx.stroke();
}; }
Palette.prepareForDrag = function (e) { static prepareForDrag (e) {
e.preventDefault(); e.preventDefault();
ScratchAudio.sndFX('grab.wav'); ScratchAudio.sndFX('grab.wav');
if (!ScratchJr.runtime.inactive()) { if (!ScratchJr.runtime.inactive()) {
@ -254,9 +280,9 @@ Palette.prepareForDrag = function (e) {
// Events.dragcanvas.owner.lift(); // Events.dragcanvas.owner.lift();
sc.dragList = [Events.dragcanvas.owner]; sc.dragList = [Events.dragcanvas.owner];
sc.prepareCaret(Events.dragcanvas.owner); sc.prepareCaret(Events.dragcanvas.owner);
}; }
Palette.getBlockNamed = function (str) { static getBlockNamed (str) {
var pal = gn('palette'); var pal = gn('palette');
for (var i = 0; i < pal.childElementCount; i++) { for (var i = 0; i < pal.childElementCount; i++) {
if (pal.childNodes[i].owner.blocktype == str) { if (pal.childNodes[i].owner.blocktype == str) {
@ -264,9 +290,9 @@ Palette.getBlockNamed = function (str) {
} }
} }
return null; return null;
}; }
Palette.createSelector = function (parent, n, dx, dy, spec) { static createSelector (parent, n, dx, dy, spec) {
var pxWidth = 51 * scaleMultiplier; var pxWidth = 51 * scaleMultiplier;
var pxHeight = 57 * scaleMultiplier; var pxHeight = 57 * scaleMultiplier;
var div = newDiv(parent, dx, dy, pxWidth, pxHeight, { var div = newDiv(parent, dx, dy, pxWidth, pxHeight, {
@ -295,15 +321,15 @@ Palette.createSelector = function (parent, n, dx, dy, spec) {
div.ontouchstart = function (evt) { div.ontouchstart = function (evt) {
Palette.clickOnCategory(evt); Palette.clickOnCategory(evt);
}; };
}; }
Palette.getPaletteSize = function () { static getPaletteSize () {
var first = gn('palette').childNodes[0]; var first = gn('palette').childNodes[0];
var last = gn('palette').childNodes[gn('palette').childElementCount - 1]; var last = gn('palette').childNodes[gn('palette').childElementCount - 1];
return last.offsetLeft + last.offsetWidth - first.offsetLeft; return last.offsetLeft + last.offsetWidth - first.offsetLeft;
}; }
Palette.clickOnCategory = function (e) { static clickOnCategory (e) {
if (!e) { if (!e) {
return; return;
} }
@ -313,13 +339,12 @@ Palette.clickOnCategory = function (e) {
ScratchAudio.sndFX('keydown.wav'); ScratchAudio.sndFX('keydown.wav');
var index = t.parentNode ? t.parentNode.index : 2; var index = t.parentNode ? t.parentNode.index : 2;
Palette.selectCategory(index); Palette.selectCategory(index);
}; }
Palette.selectCategory = function (n) { static selectCategory (n) {
Palette.currentCategory = n;
var div = gn('selectors'); var div = gn('selectors');
// set the icons for text or sprite // set the icons for text or sprite
Palette.numcat = n; numcat = n;
var currentSel = div.childNodes[n + 1]; var currentSel = div.childNodes[n + 1];
for (var i = 1; i < div.childElementCount; i++) { for (var i = 1; i < div.childElementCount; i++) {
var sel = div.childNodes[i]; var sel = div.childNodes[i];
@ -335,15 +360,15 @@ Palette.selectCategory = function (n) {
return; return;
} }
var list = (BlockSpecs.palettes[n]).concat(); var list = (BlockSpecs.palettes[n]).concat();
var dx = Palette.dxblocks; var dx = dxblocks;
for (var k = 0; k < list.length; k++) { for (var k = 0; k < list.length; k++) {
if (list[k] == 'space') { if (list[k] == 'space') {
dx += 30 * Palette.blockscale; dx += 30 * blockscale;
} else { } else {
var newb = Palette.newScaledBlock(pal, list[k], var newb = Palette.newScaledBlock(pal, list[k],
((list[k] == 'repeat') ? 0.65 * scaleMultiplier : Palette.blockscale), dx, Palette.blockdy); ((list[k] == 'repeat') ? 0.65 * scaleMultiplier : blockscale), dx, blockdy);
newb.lift(); newb.lift();
dx += Palette.betweenblocks; dx += betweenblocks;
} }
} }
dx += 30; dx += 30;
@ -351,21 +376,21 @@ Palette.selectCategory = function (n) {
Palette.addPagesBlocks(dx); Palette.addPagesBlocks(dx);
} }
if ((n == 3) && (ScratchJr.getSprite().sounds.length > 0)) { if ((n == 3) && (ScratchJr.getSprite().sounds.length > 0)) {
Palette.addSoundsBlocks(Palette.dxblocks); Palette.addSoundsBlocks(dxblocks);
}
} }
};
Palette.reset = function () { static reset () {
if (Palette.numcat == (BlockSpecs.categories.length - 1)) { if (numcat == (BlockSpecs.categories.length - 1)) {
Palette.selectCategory(BlockSpecs.categories.length - 1); Palette.selectCategory(BlockSpecs.categories.length - 1);
} }
if (Palette.numcat == 3) { if (numcat == 3) {
Palette.selectCategory(3); Palette.selectCategory(3);
} }
}; }
Palette.showSelectors = function (b) { static showSelectors (b) {
var n = Palette.numcat; var n = numcat;
var div = gn('selectors'); var div = gn('selectors');
for (var i = 0; i < div.childElementCount; i++) { for (var i = 0; i < div.childElementCount; i++) {
var sel = div.childNodes[i]; var sel = div.childNodes[i];
@ -374,9 +399,9 @@ Palette.showSelectors = function (b) {
sel.childNodes[2].style.visibility = (sel.index != n) && b ? 'visible' : 'hidden'; sel.childNodes[2].style.visibility = (sel.index != n) && b ? 'visible' : 'hidden';
sel.childNodes[3].style.visibility = (sel.index == n) && b ? 'visible' : 'hidden'; sel.childNodes[3].style.visibility = (sel.index == n) && b ? 'visible' : 'hidden';
} }
}; }
Palette.addPagesBlocks = function (dx) { static addPagesBlocks (dx) {
var pal = gn('palette'); var pal = gn('palette');
var spec = BlockSpecs.defs.gotopage; var spec = BlockSpecs.defs.gotopage;
for (var i = 0; i < ScratchJr.stage.pages.length; i++) { for (var i = 0; i < ScratchJr.stage.pages.length; i++) {
@ -384,38 +409,38 @@ Palette.addPagesBlocks = function (dx) {
continue; continue;
} }
spec[4] = i + 1; spec[4] = i + 1;
var newb = Palette.newScaledBlock(pal, 'gotopage', Palette.blockscale, dx, Palette.blockdy); var newb = Palette.newScaledBlock(pal, 'gotopage', blockscale, dx, blockdy);
newb.lift(); newb.lift();
dx += Palette.betweenblocks + 5; dx += betweenblocks + 5;
}
} }
};
Palette.addSoundsBlocks = function (dx) { static addSoundsBlocks (dx) {
var pal = gn('palette'); var pal = gn('palette');
var spr = ScratchJr.getSprite(); var spr = ScratchJr.getSprite();
var list = spr ? spr.sounds : []; var list = spr ? spr.sounds : [];
for (var i = 0; i < list.length; i++) { for (var i = 0; i < list.length; i++) {
var op = (MediaLib.sounds.indexOf(list[i]) < 0) ? 'playusersnd' : 'playsnd'; var op = (MediaLib.sounds.indexOf(list[i]) < 0) ? 'playusersnd' : 'playsnd';
var val = (MediaLib.sounds.indexOf(list[i]) < 0) ? i : list[i]; var val = (MediaLib.sounds.indexOf(list[i]) < 0) ? i : list[i];
var newb = Palette.addBlockSound(pal, op, val, dx, Palette.blockdy); var newb = Palette.addBlockSound(pal, op, val, dx, blockdy);
newb.lift(); newb.lift();
dx += Palette.betweenblocks; dx += betweenblocks;
} }
if ((list.length < 6) && Record.available) { if ((list.length < 6) && Record.available) {
Palette.drawRecordSound(newb.div.offsetWidth, newb.div.offsetHeight, dx); Palette.drawRecordSound(newb.div.offsetWidth, newb.div.offsetHeight, dx);
} }
}; }
Palette.addBlockSound = function (parent, op, val, dx, dy) { static addBlockSound (parent, op, val, dx, dy) {
var spec = BlockSpecs.defs[op]; var spec = BlockSpecs.defs[op];
var old = spec[4]; var old = spec[4];
spec[4] = val; spec[4] = val;
var newb = Palette.newScaledBlock(parent, op, Palette.blockscale, dx, dy); var newb = Palette.newScaledBlock(parent, op, blockscale, dx, dy);
spec[4] = old; spec[4] = old;
return newb; return newb;
}; }
Palette.drawRecordSound = function (w, h, dx) { static drawRecordSound (w, h, dx) {
var pal = gn('palette'); var pal = gn('palette');
var div = newDiv(pal, dx, 0, w, h, { var div = newDiv(pal, dx, 0, w, h, {
top: (6 * scaleMultiplier) + 'px' top: (6 * scaleMultiplier) + 'px'
@ -442,23 +467,23 @@ Palette.drawRecordSound = function (w, h, dx) {
if (isTablet) { if (isTablet) {
div.ontouchstart = Palette.recordSound; div.ontouchstart = Palette.recordSound;
} }
}; }
Palette.recordSound = function (e) { static recordSound (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
ScratchJr.clearSelection(); ScratchJr.clearSelection();
Record.appear(); Record.appear();
}; }
Palette.inStatesPalette = function () { static inStatesPalette () {
var div = gn('selectors'); var div = gn('selectors');
var sel = div.childNodes[div.childElementCount - 1]; var sel = div.childNodes[div.childElementCount - 1];
return sel.childNodes[0].style.visibility == 'hidden'; return sel.childNodes[0].style.visibility == 'hidden';
}; }
// move to scratch jr app // move to scratch jr app
Palette.getLandingPlace = function (el, e, scale) { static getLandingPlace (el, e, scale) {
scale = typeof scale !== 'undefined' ? scale : 1; scale = typeof scale !== 'undefined' ? scale : 1;
var sc = ScratchJr.getActiveScript().owner; var sc = ScratchJr.getActiveScript().owner;
var pt = e ? Events.getTargetPoint(e) : null; var pt = e ? Events.getTargetPoint(e) : null;
@ -491,20 +516,20 @@ Palette.getLandingPlace = function (el, e, scale) {
return 'pages'; return 'pages';
} }
return null; return null;
}; }
Palette.overlapsWith = function (el, box) { static overlapsWith (el, box) {
var box2 = new Rectangle(globalx(el), globaly(el), el.offsetWidth, el.offsetHeight); var box2 = new Rectangle(globalx(el), globaly(el), el.offsetWidth, el.offsetHeight);
return box.intersects(box2); return box.intersects(box2);
}; }
Palette.overlapsWith2 = function (el, box) { static overlapsWith2 (el, box) {
var box2 = new Rectangle(el.offsetLeft, el.offsetTop, el.offsetWidth, el.offsetHeight); var box2 = new Rectangle(el.offsetLeft, el.offsetTop, el.offsetWidth, el.offsetHeight);
return box.intersects(box2); return box.intersects(box2);
}; }
Palette.getBlockfromChild = function (div) { static getBlockfromChild (div) {
while (div != null) { while (div != null) {
if (div.owner) { if (div.owner) {
return div; return div;
@ -512,9 +537,9 @@ Palette.getBlockfromChild = function (div) {
div = div.parentNode; div = div.parentNode;
} }
return null; return null;
}; }
Palette.getHittedThumb = function (el, div, scale) { static getHittedThumb (el, div, scale) {
scale = typeof scale !== 'undefined' ? scale : 1; scale = typeof scale !== 'undefined' ? scale : 1;
var box1 = new Rectangle(el.left / scale, el.top / scale, el.offsetWidth / scale, el.offsetHeight / scale); var box1 = new Rectangle(el.left / scale, el.top / scale, el.offsetWidth / scale, el.offsetHeight / scale);
var area = 0; var area = 0;
@ -535,13 +560,13 @@ Palette.getHittedThumb = function (el, div, scale) {
} }
} }
return res; return res;
}; }
////////////////////////////////////// //////////////////////////////////////
// Palette Block // Palette Block
///////////////////////////////////// /////////////////////////////////////
Palette.newScaledBlock = function (parent, op, scale, dx, dy) { static newScaledBlock (parent, op, scale, dx, dy) {
var bbx = new Block(BlockSpecs.defs[op], true, scale); var bbx = new Block(BlockSpecs.defs[op], true, scale);
setProps(bbx.div.style, { setProps(bbx.div.style, {
position: 'absolute', position: 'absolute',
@ -550,9 +575,9 @@ Palette.newScaledBlock = function (parent, op, scale, dx, dy) {
}); });
parent.appendChild(bbx.div); parent.appendChild(bbx.div);
return bbx; return bbx;
}; }
Palette.dropBlockFromPalette = function (e, element) { static dropBlockFromPalette (e, element) {
e.preventDefault(); e.preventDefault();
switch (Palette.getLandingPlace(element, e)) { switch (Palette.getLandingPlace(element, e)) {
case 'scripts': case 'scripts':
@ -575,4 +600,5 @@ Palette.dropBlockFromPalette = function (e, element) {
break; break;
} }
ScratchJr.getActiveScript().owner.dragList = []; ScratchJr.getActiveScript().owner.dragList = [];
}; }
}

View file

@ -1,25 +1,60 @@
var Project = function () {}; import ScratchJr from '../ScratchJr';
import BlockSpecs from '../blocks/BlockSpecs';
import Alert from './Alert';
import Palette from './Palette';
import UI from './UI';
import Page from './Page';
import Sprite from '../engine/Sprite';
import iOS from '../../iPad/iOS';
import IO from '../../iPad/IO';
import Paint from '../../painteditor/Paint';
import SVG2Canvas from '../../utils/SVG2Canvas';
import {frame, gn, newHTML, scaleMultiplier, getIdFor,
isAndroid, setProps, setCanvasSize} from '../../utils/lib';
Project.metadata = undefined; let metadata = undefined;
Project.mediaCount = -1; let mediaCount = -1;
Project.saving = false; let saving = false;
Project.angle = 0; let interval = undefined;
Project.interval = undefined; let pageid;
Project.pageid; let loadIcon = undefined;
Project.loadIcon = undefined; let error = false;
Project.whenDone = undefined; let projectbarsize = 66;
Project.requestsCount = 0; let mediaCountBase = 1;
Project.error = false;
Project.projectbarsize = 66;
Project.mediaCountBase = 1;
Project.clear = function () { export default class Project {
static get metadata () {
return metadata;
}
static set metadata (newMetadata) {
metadata = newMetadata;
}
static get mediaCount () {
return mediaCount;
}
static set mediaCount (newMediaCount) {
mediaCount = newMediaCount;
}
static set loadIcon (newLoadIcon) {
loadIcon = newLoadIcon;
}
static get error () {
return error;
}
static clear () {
ScratchJr.stage.clear(); ScratchJr.stage.clear();
UI.clear(); UI.clear();
}; }
Project.load = function () { static load () {
Project.mediaCountBase = 1; mediaCountBase = 1;
ScratchJr.log('Project load status', ScratchJr.getTime(), 'sec', BlockSpecs.loadCount); ScratchJr.log('Project load status', ScratchJr.getTime(), 'sec', BlockSpecs.loadCount);
if (BlockSpecs.loadCount > 0) { if (BlockSpecs.loadCount > 0) {
setTimeout(function () { setTimeout(function () {
@ -28,9 +63,9 @@ Project.load = function () {
} else { } else {
Project.startLoad(); Project.startLoad();
} }
}; }
Project.delayLoad = function () { static delayLoad () {
if (BlockSpecs.loadCount < 1) { if (BlockSpecs.loadCount < 1) {
Project.startLoad(); Project.startLoad();
} else { } else {
@ -38,24 +73,24 @@ Project.delayLoad = function () {
Project.delayLoad(); Project.delayLoad();
}, 32); }, 32);
} }
}; }
Project.startLoad = function () { static startLoad () {
ScratchJr.log('all UI assets recieved - procced to call server', ScratchJr.getTime(), 'sec'); ScratchJr.log('all UI assets recieved - procced to call server', ScratchJr.getTime(), 'sec');
Project.setProgress(20); Project.setProgress(20);
UI.layout(); UI.layout();
IO.getObject(ScratchJr.currentProject, Project.dataRecieved); IO.getObject(ScratchJr.currentProject, Project.dataRecieved);
}; }
Project.dataRecieved = function (str) { static dataRecieved (str) {
ScratchJr.log('got project metadata', ScratchJr.getTime(), 'sec'); ScratchJr.log('got project metadata', ScratchJr.getTime(), 'sec');
var data = JSON.parse(str)[0]; var data = JSON.parse(str)[0];
Project.metadata = IO.parseProjectData(data); metadata = IO.parseProjectData(data);
Project.mediaCount = -1; mediaCount = -1;
if (Project.metadata.json) { if (metadata.json) {
Project.loadData(Project.metadata.json, doneProjectLoad); Project.loadData(metadata.json, doneProjectLoad);
} else { } else {
Project.mediaCount = 0; mediaCount = 0;
new Page(getIdFor('page')); new Page(getIdFor('page'));
Palette.selectCategory(1); Palette.selectCategory(1);
// On Android 4.2, this comes up blank the first time, so try again in 100ms. // On Android 4.2, this comes up blank the first time, so try again in 100ms.
@ -66,9 +101,9 @@ Project.dataRecieved = function (str) {
} }
function doneProjectLoad () { function doneProjectLoad () {
// Clear gift flag // Clear gift flag
if ('id' in Project.metadata) { if ('id' in metadata) {
Project.metadata.isgift = '0'; metadata.isgift = '0';
IO.setProjectIsGift(Project.metadata); IO.setProjectIsGift(metadata);
} }
Palette.selectCategory(1); Palette.selectCategory(1);
// On Android 4.2, this comes up blank the first time, so try again in 100ms. // On Android 4.2, this comes up blank the first time, so try again in 100ms.
@ -87,10 +122,10 @@ Project.dataRecieved = function (str) {
AndroidInterface.notifyEditorDoneLoading(); AndroidInterface.notifyEditorDoneLoading();
} }
} }
}; }
Project.init = function () { static init () {
ScratchJr.log('Project init', ScratchJr.getTime(), 'sec'); ScratchJr.log('Project init', ScratchJr.getTime(), 'sec');
var bd = newHTML('div', 'modal-backdrop fade', frame.parentNode); var bd = newHTML('div', 'modal-backdrop fade', frame.parentNode);
bd.setAttribute('id', 'backdrop'); bd.setAttribute('id', 'backdrop');
@ -107,17 +142,17 @@ Project.init = function () {
setProps(body.style, { setProps(body.style, {
zoom: scaleMultiplier zoom: scaleMultiplier
}); });
if (Project.loadIcon.complete) { if (loadIcon.complete) {
Project.addFeedback(); Project.addFeedback();
} else { } else {
Project.loadIcon.onload = function () { loadIcon.onload = function () {
Project.addFeedback(); Project.addFeedback();
}; };
} }
Project.drawBlind(); Project.drawBlind();
}; }
Project.addFeedback = function () { static addFeedback () {
var body = gn('modalbody'); var body = gn('modalbody');
newHTML('div', 'loadscreenfill', body); newHTML('div', 'loadscreenfill', body);
newHTML('div', 'topfill', body); newHTML('div', 'topfill', body);
@ -128,24 +163,24 @@ Project.addFeedback = function () {
var cover2 = newHTML('div', 'progressbar2', body); var cover2 = newHTML('div', 'progressbar2', body);
cover2.setAttribute('id', 'progressbar2'); cover2.setAttribute('id', 'progressbar2');
var li = newHTML('div', 'loadicon', body); var li = newHTML('div', 'loadicon', body);
li.appendChild(Project.loadIcon); li.appendChild(loadIcon);
}; }
Project.setProgress = function (perc) { static setProgress (perc) {
if (!gn('progressbar')) { if (!gn('progressbar')) {
return; return;
} }
var h = Project.projectbarsize - Math.round(Project.projectbarsize * perc / 100); var h = projectbarsize - Math.round(projectbarsize * perc / 100);
ScratchJr.log('setProgress', perc, h, Project.mediaCount, Project.mediaCountBase); ScratchJr.log('setProgress', perc, h, mediaCount, mediaCountBase);
gn('progressbar').style.height = h + 'px'; gn('progressbar').style.height = h + 'px';
if (h == 0) { if (h == 0) {
gn('progressbar2').style.height = '0px'; gn('progressbar2').style.height = '0px';
gn('topcover').style.background = '#F9A737'; gn('topcover').style.background = '#F9A737';
} }
}; }
Project.drawBlind = function () { static drawBlind () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade in'); gn('backdrop').setAttribute('class', 'modal-backdrop fade in');
setProps(gn('backdrop').style, { setProps(gn('backdrop').style, {
display: 'block' display: 'block'
@ -154,51 +189,51 @@ Project.drawBlind = function () {
display: 'block' display: 'block'
}); });
gn('modaldialog').setAttribute('class', 'modal fade in'); gn('modaldialog').setAttribute('class', 'modal fade in');
};
Project.loadwait = function (whenDone) {
if (Project.interval != null) {
window.clearInterval(Project.interval);
} }
Project.mediaCountBase = Project.mediaCount;
if (Project.mediaCount <= 0) { static loadwait (whenDone) {
if (interval != null) {
window.clearInterval(interval);
}
mediaCountBase = mediaCount;
if (mediaCount <= 0) {
Project.getStarted(whenDone); Project.getStarted(whenDone);
} else { } else {
Project.interval = window.setInterval(function () { interval = window.setInterval(function () {
Project.loadTask(whenDone); Project.loadTask(whenDone);
}, 32); }, 32);
} }
}; }
Project.loadTask = function (whenDone) { static loadTask (whenDone) {
if (Project.mediaCount <= 0) { if (mediaCount <= 0) {
Project.getStarted(whenDone); Project.getStarted(whenDone);
} else { } else {
Project.setProgress(Project.getMediaLoadRatio(70)); Project.setProgress(Project.getMediaLoadRatio(70));
} }
};
Project.getMediaLoadRatio = function (f) {
if (Project.mediaCount > Project.mediaCountBase) {
Project.mediaCountBase = Project.mediaCount;
} }
return 20 + f - (Project.mediaCount / Project.mediaCountBase) * f;
};
Project.getStarted = function (whenDone) { static getMediaLoadRatio (f) {
if (mediaCount > mediaCountBase) {
mediaCountBase = mediaCount;
}
return 20 + f - (mediaCount / mediaCountBase) * f;
}
static getStarted (whenDone) {
Project.setProgress(90); Project.setProgress(90);
if (Project.interval) { if (interval) {
window.clearInterval(Project.interval); window.clearInterval(interval);
} }
Project.interval = null; interval = null;
ScratchJr.log('Project images retrieved from server', ScratchJr.getTime(), 'sec'); ScratchJr.log('Project images retrieved from server', ScratchJr.getTime(), 'sec');
Project.setLoadPage(Project.pageid, whenDone); Project.setLoadPage(pageid, whenDone);
ScratchJr.log('load done', ScratchJr.getTime(), 'sec', '-- media missing = ', Project.mediaCount); ScratchJr.log('load done', ScratchJr.getTime(), 'sec', '-- media missing = ', mediaCount);
ScratchJr.stage.resetPages(); ScratchJr.stage.resetPages();
ScratchJr.runtime.beginTimer(); ScratchJr.runtime.beginTimer();
}; }
Project.liftCurtain = function () { static liftCurtain () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade'); gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, { setProps(gn('backdrop').style, {
display: 'none' display: 'none'
@ -207,9 +242,9 @@ Project.liftCurtain = function () {
setProps(gn('modaldialog').style, { setProps(gn('modaldialog').style, {
display: 'none' display: 'none'
}); });
}; }
Project.setLoadPage = function (pageid, whenDone) { static setLoadPage (pageid, whenDone) {
ScratchJr.log('setLoadPage', ScratchJr.getTime(), 'sec'); ScratchJr.log('setLoadPage', ScratchJr.getTime(), 'sec');
var pages = ScratchJr.stage.getPagesID(); var pages = ScratchJr.stage.getPagesID();
if (pages.indexOf(pageid) < 0) { if (pages.indexOf(pageid) < 0) {
@ -229,44 +264,44 @@ Project.setLoadPage = function (pageid, whenDone) {
if (whenDone) { if (whenDone) {
whenDone(); whenDone();
} }
}; }
Project.loadData = function (data, fcn) { static loadData (data, fcn) {
try { try {
data = (typeof data === 'string') ? JSON.parse(data) : data; data = (typeof data === 'string') ? JSON.parse(data) : data;
Project.mediaCount = 0; mediaCount = 0;
Project.loadme(data, fcn); Project.loadme(data, fcn);
Project.error = false; error = false;
} catch (e) { } catch (e) {
console.log(e); //eslint-disable-line no-console console.log(e); //eslint-disable-line no-console
var errorMessage = 'Error -- project data corrupted.'; var errorMessage = 'Error -- project data corrupted.';
if (window.reloadDebug) { if (window.reloadDebug) {
document.write(e.message + '\n' + Project.metadata['json']); document.write(e.message + '\n' + metadata['json']);
return; return;
} }
Alert.open(frame, gn('flip'), errorMessage, '#ff0000'); Alert.open(frame, gn('flip'), errorMessage, '#ff0000');
if (Project.interval) { if (interval) {
window.clearInterval(Project.interval); window.clearInterval(interval);
} }
Project.interval = null; interval = null;
Palette.selectCategory(1); Palette.selectCategory(1);
// On Android 4.2, this comes up blank the first time, so try again in 100ms. // On Android 4.2, this comes up blank the first time, so try again in 100ms.
setTimeout(function () { setTimeout(function () {
Palette.selectCategory(1); Palette.selectCategory(1);
}, 100); }, 100);
Project.liftCurtain(); Project.liftCurtain();
Project.error = true; error = true;
}
} }
};
Project.loadme = function (data, fcn) { static loadme (data, fcn) {
Project.recreate(data); Project.recreate(data);
Project.loadwait(fcn); Project.loadwait(fcn);
}; }
Project.getLoadType = function (bkgid, sid, cid) { static getLoadType (bkgid, sid, cid) {
if (bkgid != null) { if (bkgid != null) {
return 'bkg'; return 'bkg';
} }
@ -277,47 +312,47 @@ Project.getLoadType = function (bkgid, sid, cid) {
return 'modify'; return 'modify';
} }
return 'add'; return 'add';
}; }
////////////////////////////////////////////////// //////////////////////////////////////////////////
// load project data // load project data
////////////////////////////////////////////////// //////////////////////////////////////////////////
Project.recreate = function (data) { static recreate (data) {
ScratchJr.log('Project data structures start loading', ScratchJr.getTime(), 'sec'); ScratchJr.log('Project data structures start loading', ScratchJr.getTime(), 'sec');
Project.mediaCount = 0; mediaCount = 0;
ScratchJr.stage.pages = []; ScratchJr.stage.pages = [];
var pages = data.pages; var pages = data.pages;
Project.pageid = data.currentPage; pageid = data.currentPage;
for (var i = 0; i < pages.length; i++) { for (var i = 0; i < pages.length; i++) {
Project.recreatePage(pages[i], data[pages[i]]); Project.recreatePage(pages[i], data[pages[i]]);
} }
Project.mediaCountBase = Project.mediaCount; mediaCountBase = mediaCount;
}; }
Project.recreatePage = function (name, data, fcn) { static recreatePage (name, data, fcn) {
var page = new Page(name, data, fcn); var page = new Page(name, data, fcn);
page.div.style.visibility = 'hidden'; page.div.style.visibility = 'hidden';
}; }
Project.substractCount = function () { static substractCount () {
Project.mediaCount--; mediaCount--;
if ((gn('backdrop').className != 'modal-backdrop fade in') || (Project.mediaCountBase == 0)) { if ((gn('backdrop').className != 'modal-backdrop fade in') || (mediaCountBase == 0)) {
return; return;
} }
Project.setProgress(Project.getMediaLoadRatio(70)); Project.setProgress(Project.getMediaLoadRatio(70));
}; }
Project.recreateObject = function (page, name, data, callBack, active) { static recreateObject (page, name, data, callBack, active) {
var list = data.scripts; var list = data.scripts;
//delete data.scripts; //delete data.scripts;
var spr; var spr;
data.page = page; data.page = page;
if (data.type == 'sprite') { if (data.type == 'sprite') {
Project.mediaCount++; mediaCount++;
var fcn = function (spr) { var fcn = function (spr) {
spr.setPos(data.xcoor, data.ycoor); spr.setPos(data.xcoor, data.ycoor);
Project.mediaCount--; mediaCount--;
if (gn('backdrop').className == 'modal-backdrop fade in') { if (gn('backdrop').className == 'modal-backdrop fade in') {
Project.setProgress(Project.getMediaLoadRatio(70)); Project.setProgress(Project.getMediaLoadRatio(70));
} }
@ -345,35 +380,35 @@ Project.recreateObject = function (page, name, data, callBack, active) {
} }
spr.div.style.opacity = spr.shown ? 1 : 0; spr.div.style.opacity = spr.shown ? 1 : 0;
return spr; return spr;
}; }
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Save project data // Save project data
////////////////////////////////////////////////// //////////////////////////////////////////////////
Project.prepareToSave = function (id, whenDone) { static prepareToSave (id, whenDone) {
if (Project.saving) { if (saving) {
Alert.open(frame, gn('flip'), 'Waiting', '#28A5DA'); Alert.open(frame, gn('flip'), 'Waiting', '#28A5DA');
Project.waitUntilSaved(id, whenDone); Project.waitUntilSaved(id, whenDone);
} else { } else {
Alert.open(frame, gn('flip'), 'Saving', '#28A5DA'); Alert.open(frame, gn('flip'), 'Saving', '#28A5DA');
Project.save(id, whenDone); Project.save(id, whenDone);
} }
}; }
Project.waitUntilSaved = function (id, fcn) { static waitUntilSaved (id, fcn) {
if (Project.saving) { if (saving) {
setTimeout(function () { setTimeout(function () {
Project.waitUntilSaved(id, fcn); Project.waitUntilSaved(id, fcn);
}, 500); }, 500);
} else { } else {
Project.save(id, fcn); Project.save(id, fcn);
} }
}; }
// Determine if thumbnailMD5 is unique to projectID // Determine if thumbnailMD5 is unique to projectID
// callback(true/false) // callback(true/false)
Project.thumbnailUnique = function (thumbnailMD5, projectID, callback) { static thumbnailUnique (thumbnailMD5, projectID, callback) {
var json = {}; var json = {};
json.cond = 'deleted = ? AND id != ? AND gallery IS NULL'; json.cond = 'deleted = ? AND id != ? AND gallery IS NULL';
json.items = ['name', 'thumbnail', 'id']; json.items = ['name', 'thumbnail', 'id'];
@ -395,11 +430,11 @@ Project.thumbnailUnique = function (thumbnailMD5, projectID, callback) {
} }
callback(isUnique); callback(isUnique);
}); });
}; }
Project.save = function (id, whenDone) { static save (id, whenDone) {
Project.saving = true; saving = true;
var th = Project.metadata.thumbnail; var th = metadata.thumbnail;
if (th && ScratchJr.editmode != 'storyStarter') { // Don't try to delete the thumbnail in a sample project if (th && ScratchJr.editmode != 'storyStarter') { // Don't try to delete the thumbnail in a sample project
var thumb = (typeof th === 'string') ? JSON.parse(th) : th; var thumb = (typeof th === 'string') ? JSON.parse(th) : th;
if (thumb.md5.indexOf('samples/') < 0) { // In case we've exited story-starter mode if (thumb.md5.indexOf('samples/') < 0) { // In case we've exited story-starter mode
@ -410,8 +445,8 @@ Project.save = function (id, whenDone) {
}); });
} }
} }
Project.metadata.id = id; metadata.id = id;
Project.metadata.json = Project.getProject(ScratchJr.stage.pages[0].id); metadata.json = Project.getProject(ScratchJr.stage.pages[0].id);
Project.getThumbnailPNG(ScratchJr.stage.pages[0], 192, 144, getMD5); Project.getThumbnailPNG(ScratchJr.stage.pages[0], 192, 144, getMD5);
function getMD5 (dataurl) { function getMD5 (dataurl) {
var pngBase64 = dataurl.split(',')[1]; var pngBase64 = dataurl.split(',')[1];
@ -426,23 +461,23 @@ Project.save = function (id, whenDone) {
} }
function doNext (md5) { function doNext (md5) {
Project.metadata.thumbnail = { metadata.thumbnail = {
'pagecount': ScratchJr.stage.pages.length, 'pagecount': ScratchJr.stage.pages.length,
'md5': md5 'md5': md5
}; };
Project.metadata.mtime = (new Date()).getTime().toString(); metadata.mtime = (new Date()).getTime().toString();
IO.saveProject(Project.metadata, saveDone); IO.saveProject(metadata, saveDone);
} }
function saveDone () { function saveDone () {
Project.saving = false; saving = false;
if (whenDone) { if (whenDone) {
whenDone(); whenDone();
} }
} }
}; }
Project.getProject = function (pageid) { static getProject (pageid) {
var obj = {}; var obj = {};
obj.pages = ScratchJr.stage.getPagesID(); obj.pages = ScratchJr.stage.getPagesID();
obj.currentPage = pageid; obj.currentPage = pageid;
@ -450,17 +485,17 @@ Project.getProject = function (pageid) {
obj[ScratchJr.stage.pages[i].id] = ScratchJr.stage.pages[i].encodePage(); obj[ScratchJr.stage.pages[i].id] = ScratchJr.stage.pages[i].encodePage();
} }
return obj; return obj;
}; }
Project.getUndo = function () { static getUndo () {
return Project.getProject(ScratchJr.stage.currentPage.id); return Project.getProject(ScratchJr.stage.currentPage.id);
}; }
Project.encodeSprite = function (name) { static encodeSprite (name) {
return gn(name).owner.getData(); return gn(name).owner.getData();
}; }
Project.encodeStrip = function (b) { static encodeStrip (b) {
var res = []; var res = [];
var hasargs = ['playsnd', 'gotopage', 'playusersnd', 'setcolor', 'onmessage', 'message', 'setspeed']; var hasargs = ['playsnd', 'gotopage', 'playusersnd', 'setcolor', 'onmessage', 'message', 'setspeed'];
var loops = ['repeat']; var loops = ['repeat'];
@ -491,13 +526,13 @@ Project.encodeStrip = function (b) {
b = b.next; b = b.next;
} }
return res; return res;
}; }
///////////////////////////// /////////////////////////////
// Project PNG Thumbnail // Project PNG Thumbnail
///////////////////////////// /////////////////////////////
Project.getThumbnailPNG = function (page, w, h, fcn) { static getThumbnailPNG (page, w, h, fcn) {
var scale = w / 480; var scale = w / 480;
var data = {}; var data = {};
data.pagecount = ScratchJr.stage.pages.length; data.pagecount = ScratchJr.stage.pages.length;
@ -520,16 +555,16 @@ Project.getThumbnailPNG = function (page, w, h, fcn) {
ctx.drawImage(pcnv, 0, 0, 480, 360, 0, 0, w, h); ctx.drawImage(pcnv, 0, 0, 480, 360, 0, 0, w, h);
Project.drawSprites(page, scale, c, w, h, fcn); Project.drawSprites(page, scale, c, w, h, fcn);
} }
}; }
Project.drawPNGInCanvas = function (png, w, h) { static drawPNGInCanvas (png, w, h) {
var srccnv = document.createElement('canvas'); var srccnv = document.createElement('canvas');
setCanvasSize(srccnv, w, h); setCanvasSize(srccnv, w, h);
var ctx = srccnv.getContext('2d'); var ctx = srccnv.getContext('2d');
ctx.drawImage(png, 0, 0, w, h); ctx.drawImage(png, 0, 0, w, h);
return srccnv; return srccnv;
}; }
Project.drawSVGinCanvas = function (extxml, w, h) { static drawSVGinCanvas (extxml, w, h) {
var srccnv = document.createElement('canvas'); var srccnv = document.createElement('canvas');
setCanvasSize(srccnv, w, h); setCanvasSize(srccnv, w, h);
var ctx = srccnv.getContext('2d'); var ctx = srccnv.getContext('2d');
@ -537,18 +572,18 @@ Project.drawSVGinCanvas = function (extxml, w, h) {
SVG2Canvas.drawLayer(extxml.childNodes[i], ctx, SVG2Canvas.drawLayer); SVG2Canvas.drawLayer(extxml.childNodes[i], ctx, SVG2Canvas.drawLayer);
} }
return srccnv; return srccnv;
}; }
Project.maskBorders = function (ctx, w, h) { static maskBorders (ctx, w, h) {
ctx.save(); ctx.save();
ctx.globalCompositeOperation = 'destination-in'; ctx.globalCompositeOperation = 'destination-in';
if (Settings.edition != 'PBS') { if (Settings.edition != 'PBS') {
ctx.drawImage(BlockSpecs.projectThumb, 0, 0, w, h); ctx.drawImage(BlockSpecs.projectThumb, 0, 0, w, h);
} }
ctx.restore(); ctx.restore();
}; }
Project.drawSprites = function (page, scale, c, w, h, fcn) { static drawSprites (page, scale, c, w, h, fcn) {
var ctx = c.getContext('2d'); var ctx = c.getContext('2d');
doNext(1); doNext(1);
function doNext (n) { function doNext (n) {
@ -570,4 +605,5 @@ Project.drawSprites = function (page, scale, c, w, h, fcn) {
doNext(n + 1); doNext(n + 1);
} }
}; }
}

View file

@ -1,18 +1,35 @@
var Record = function () {}; import ScratchJr from '../ScratchJr';
import Palette from './Palette';
import Undo from './Undo';
import iOS from '../../iPad/iOS';
import ScratchAudio from '../../utils/ScratchAudio';
import {frame, gn, newHTML, isTablet, isAndroid, setProps} from '../../utils/lib';
Record.isAndroid = isAndroid; let interval = null;
Record.interval = null; let recordedSound = null;
Record.recordedSound = null; let isRecording = false;
Record.isRecording = false; let isPlaying = false;
Record.isPlaying = false; let available = true;
Record.available = true; let error = false;
Record.error = false; let dialogOpen = false;
Record.dialogOpen = false; let timeLimit = null;
Record.timeLimit = null; let playTimeLimit = null;
Record.playTimeLimit = null;
// Create the recording window, including buttons and volume indicators export default class Record {
Record.init = function () { static get available () {
return available;
}
static set available (newAvailable) {
available = newAvailable;
}
static get dialogOpen () {
return dialogOpen;
}
// Create the recording window, including buttons and volume indicators
static init () {
var modal = newHTML('div', 'record fade', frame); var modal = newHTML('div', 'record fade', frame);
modal.setAttribute('id', 'recorddialog'); modal.setAttribute('id', 'recorddialog');
var topbar = newHTML('div', 'toolbar', modal); var topbar = newHTML('div', 'toolbar', modal);
@ -39,21 +56,21 @@ Record.init = function () {
for (var j = 0; j < lib.length; j++) { for (var j = 0; j < lib.length; j++) {
Record.newToggleClicky(ctrol, 'id_', lib[j][0], lib[j][1]); Record.newToggleClicky(ctrol, 'id_', lib[j][0], lib[j][1]);
} }
}; }
// Dialog box hide/show // Dialog box hide/show
Record.appear = function () { static appear () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade in'); gn('backdrop').setAttribute('class', 'modal-backdrop fade in');
setProps(gn('backdrop').style, { setProps(gn('backdrop').style, {
display: 'block' display: 'block'
}); });
gn('recorddialog').setAttribute('class', 'record fade in'); gn('recorddialog').setAttribute('class', 'record fade in');
ScratchJr.stopStrips(); ScratchJr.stopStrips();
Record.dialogOpen = true; dialogOpen = true;
ScratchJr.onBackButtonCallback.push(Record.saveSoundandClose); ScratchJr.onBackButtonCallback.push(Record.saveSoundandClose);
}; }
Record.disappear = function () { static disappear () {
setTimeout(function () { setTimeout(function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade'); gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, { setProps(gn('backdrop').style, {
@ -61,12 +78,12 @@ Record.disappear = function () {
}); });
gn('recorddialog').setAttribute('class', 'record fade'); gn('recorddialog').setAttribute('class', 'record fade');
}, 333); }, 333);
Record.dialogOpen = false; dialogOpen = false;
ScratchJr.onBackButtonCallback.pop(); ScratchJr.onBackButtonCallback.pop();
}; }
// Register toggle buttons and handlers // Register toggle buttons and handlers
Record.newToggleClicky = function (p, prefix, key, fcn) { static newToggleClicky (p, prefix, key, fcn) {
var button = newHTML('div', 'controlwrap', p); var button = newHTML('div', 'controlwrap', p);
newHTML('div', key + 'snd off', button); newHTML('div', key + 'snd off', button);
button.setAttribute('type', 'toggleclicky'); button.setAttribute('type', 'toggleclicky');
@ -83,267 +100,268 @@ Record.newToggleClicky = function (p, prefix, key, fcn) {
} }
} }
return button; return button;
}; }
// Toggle button appearance on/off // Toggle button appearance on/off
Record.toggleButtonUI = function (button, newState) { static toggleButtonUI (button, newState) {
var element = 'id_' + button; var element = 'id_' + button;
var newStateStr = (newState) ? 'on' : 'off'; var newStateStr = (newState) ? 'on' : 'off';
var attrclass = button + 'snd'; var attrclass = button + 'snd';
gn(element).childNodes[0].setAttribute('class', attrclass + ' ' + newStateStr); gn(element).childNodes[0].setAttribute('class', attrclass + ' ' + newStateStr);
}; }
// Volume UI updater // Volume UI updater
Record.updateVolume = function (f) { static updateVolume (f) {
var num = Math.round(f * 13); var num = Math.round(f * 13);
var div = gn('soundvolume'); var div = gn('soundvolume');
if (!Record.isRecording) { if (!isRecording) {
num = 0; num = 0;
} }
for (var i = 0; i < 13; i++) { for (var i = 0; i < 13; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', ((i > num) ? 'soundlevel off' : 'soundlevel on')); div.childNodes[i].childNodes[0].setAttribute('class', ((i > num) ? 'soundlevel off' : 'soundlevel on'));
} }
}; }
// Stop recording UI and turn off volume levels // Stop recording UI and turn off volume levels
Record.recordUIoff = function () { static recordUIoff () {
Record.toggleButtonUI('record', false); Record.toggleButtonUI('record', false);
var div = gn('soundvolume'); var div = gn('soundvolume');
for (var i = 0; i < gn('soundvolume').childElementCount; i++) { for (var i = 0; i < gn('soundvolume').childElementCount; i++) {
div.childNodes[i].childNodes[0].setAttribute('class', 'soundlevel off'); div.childNodes[i].childNodes[0].setAttribute('class', 'soundlevel off');
} }
}; }
// On press record button // On press record button
Record.record = function (e) { static record (e) {
if (Record.error) { if (error) {
Record.killRecorder(e); Record.killRecorder(e);
return; return;
} }
if (Record.isPlaying) { if (isPlaying) {
Record.stopPlayingSound(doRecord); Record.stopPlayingSound(doRecord);
} else { } else {
doRecord(); doRecord();
} }
function doRecord () { function doRecord () {
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(); // Stop if we're already recording Record.stopRecording(); // Stop if we're already recording
} else { } else {
iOS.sndrecord(Record.startRecording); // Start a recording iOS.sndrecord(Record.startRecording); // Start a recording
} }
} }
}; }
Record.startRecording = function (filename) { static startRecording (filename) {
if (parseInt(filename) < 0) { if (parseInt(filename) < 0) {
// Error in getting record filename - go back to editor // Error in getting record filename - go back to editor
Record.recordedSound = undefined; recordedSound = undefined;
Record.isRecording = false; isRecording = false;
Record.killRecorder(); Record.killRecorder();
Palette.selectCategory(3); Palette.selectCategory(3);
} else { } else {
// Save recording's filename for later // Save recording's filename for later
Record.recordedSound = filename; recordedSound = filename;
Record.isRecording = true; isRecording = true;
Record.error = false; error = false;
Record.soundname = filename; Record.soundname = filename;
Record.toggleButtonUI('record', true); Record.toggleButtonUI('record', true);
var poll = function () { var poll = function () {
iOS.volume(Record.updateVolume, Record.recordError); iOS.volume(Record.updateVolume, Record.recordError);
}; };
Record.interval = setInterval(poll, 33); interval = setInterval(poll, 33);
Record.timeLimit = setTimeout(function () { timeLimit = setTimeout(function () {
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(); Record.stopRecording();
} }
}, 60000); }, 60000);
} }
}; }
// Press the play button // Press the play button
Record.playSnd = function (e) { static playSnd (e) {
if (Record.error) { if (error) {
Record.killRecorder(e); Record.killRecorder(e);
return; return;
} }
if (!Record.recordedSound) { if (!recordedSound) {
return; return;
} }
if (Record.isPlaying) { if (isPlaying) {
Record.stopPlayingSound(); Record.stopPlayingSound();
} else { } else {
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(Record.startPlaying); Record.stopRecording(Record.startPlaying);
} else { } else {
Record.startPlaying(); Record.startPlaying();
} }
} }
}; }
// Start playing the sound and switch UI appropriately // Start playing the sound and switch UI appropriately
Record.startPlaying = function () { static startPlaying () {
iOS.startplay(Record.timeOutPlay); iOS.startplay(Record.timeOutPlay);
Record.toggleButtonUI('play', true); Record.toggleButtonUI('play', true);
Record.isPlaying = true; isPlaying = true;
}; }
// Gets the sound duration from iOS and changes play UI state after time // Gets the sound duration from iOS and changes play UI state after time
Record.timeOutPlay = function (timeout) { static timeOutPlay (timeout) {
if (parseInt(timeout) < 0) { if (parseInt(timeout) < 0) {
timeout = 0.1; // Error - stop playing immediately timeout = 0.1; // Error - stop playing immediately
} }
Record.playTimeLimit = setTimeout(function () { playTimeLimit = setTimeout(function () {
Record.toggleButtonUI('play', false); Record.toggleButtonUI('play', false);
Record.isPlaying = false; isPlaying = false;
}, timeout * 1000); }, timeout * 1000);
}; }
// Press on stop // Press on stop
Record.stopSnd = function (e) { static stopSnd (e) {
if (Record.error) { if (error) {
Record.killRecorder(e); Record.killRecorder(e);
return; return;
} }
if (!Record.recordedSound) { if (!recordedSound) {
return; return;
} }
Record.flashStopButton(); Record.flashStopButton();
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(); Record.stopRecording();
} else if (Record.isPlaying) { } else if (isPlaying) {
Record.stopPlayingSound(); Record.stopPlayingSound();
} }
}; }
Record.flashStopButton = function () { static flashStopButton () {
Record.toggleButtonUI('stop', true); Record.toggleButtonUI('stop', true);
setTimeout(function () { setTimeout(function () {
Record.toggleButtonUI('stop', false); Record.toggleButtonUI('stop', false);
}, 200); }, 200);
}; }
// Stop playing the sound and switch UI appropriately // Stop playing the sound and switch UI appropriately
Record.stopPlayingSound = function (fcn) { static stopPlayingSound (fcn) {
iOS.stopplay(fcn); iOS.stopplay(fcn);
Record.toggleButtonUI('play', false); Record.toggleButtonUI('play', false);
Record.isPlaying = false; isPlaying = false;
window.clearTimeout(Record.playTimeLimit); window.clearTimeout(playTimeLimit);
Record.playTimeLimit = null; playTimeLimit = null;
};
// Stop the volume monitor and recording
Record.stopRecording = function (fcn) {
if (Record.timeLimit != null) {
clearTimeout(Record.timeLimit);
Record.timeLimit = null;
} }
if (Record.interval != null) {
window.clearInterval(Record.interval); // Stop the volume monitor and recording
Record.interval = null; static stopRecording (fcn) {
if (timeLimit != null) {
clearTimeout(timeLimit);
timeLimit = null;
}
if (interval != null) {
window.clearInterval(interval);
interval = null;
setTimeout(function () { setTimeout(function () {
Record.volumeCheckStopped(fcn); Record.volumeCheckStopped(fcn);
}, 33); }, 33);
} else { } else {
Record.volumeCheckStopped(fcn); Record.volumeCheckStopped(fcn);
} }
}; }
Record.volumeCheckStopped = function (fcn) { static volumeCheckStopped (fcn) {
Record.isRecording = false; isRecording = false;
Record.recordUIoff(); Record.recordUIoff();
iOS.recordstop(fcn); iOS.recordstop(fcn);
}; }
// Press OK (check) // Press OK (check)
Record.saveSoundAndClose = function () { static saveSoundAndClose () {
if (Record.error || !Record.recordedSound) { if (error || !recordedSound) {
Record.killRecorder(); Record.killRecorder();
} else { } else {
if (Record.isPlaying) { if (isPlaying) {
Record.stopPlayingSound(Record.closeContinueSave); Record.stopPlayingSound(Record.closeContinueSave);
} else { } else {
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(Record.closeContinueSave); Record.stopRecording(Record.closeContinueSave);
} else { } else {
Record.closeContinueSave(); Record.closeContinueSave();
} }
} }
} }
}; }
Record.closeContinueSave = function () { static closeContinueSave () {
iOS.recorddisappear('YES', Record.getUserSound); iOS.recorddisappear('YES', Record.getUserSound);
}; }
Record.closeContinueRemove = function () { static closeContinueRemove () {
// don't get the sound - proceed right to tearDown // don't get the sound - proceed right to tearDown
iOS.recorddisappear('NO', Record.tearDownRecorder); iOS.recorddisappear('NO', Record.tearDownRecorder);
}; }
Record.getUserSound = function () { static getUserSound () {
Record.isRecording = false; isRecording = false;
if (!Record.isAndroid) { if (!isAndroid) {
iOS.getmedia(Record.recordedSound, Record.registerProjectSound); iOS.getmedia(recordedSound, Record.registerProjectSound);
} else { } else {
// On Android, just pass URL // On Android, just pass URL
Record.registerProjectSound(null); Record.registerProjectSound(null);
} }
}; }
Record.registerProjectSound = function (data) { static registerProjectSound (data) {
function loadingDone (snd) { function loadingDone (snd) {
if (snd != 'error') { if (snd != 'error') {
var spr = ScratchJr.getSprite(); var spr = ScratchJr.getSprite();
var page = spr.div.parentNode.owner; var page = spr.div.parentNode.owner;
spr.sounds.push(Record.recordedSound); spr.sounds.push(recordedSound);
Undo.record({ Undo.record({
action: 'recordsound', action: 'recordsound',
who: spr.id, who: spr.id,
where: page.id, where: page.id,
sound: Record.recordedSound sound: recordedSound
}); });
ScratchJr.storyStart('Record.registerProjectSound'); ScratchJr.storyStart('Record.registerProjectSound');
} }
Record.tearDownRecorder(); Record.tearDownRecorder();
Palette.selectCategory(3); Palette.selectCategory(3);
} }
if (!Record.isAndroid) { if (!isAndroid) {
ScratchAudio.loadFromData(Record.recordedSound, data, loadingDone); ScratchAudio.loadFromData(recordedSound, data, loadingDone);
} else { } else {
// On Android, just pass URL // On Android, just pass URL
ScratchAudio.loadFromLocal(Record.recordedSound, loadingDone); ScratchAudio.loadFromLocal(recordedSound, loadingDone);
}
} }
};
// Called on error - remove everything and hide the recorder // Called on error - remove everything and hide the recorder
Record.killRecorder = function () { static killRecorder () {
// Inform iOS and then tear-down // Inform iOS and then tear-down
if (Record.isPlaying) { if (isPlaying) {
Record.stopPlayingSound(Record.closeContinueRemove); // stop playing and tear-down Record.stopPlayingSound(Record.closeContinueRemove); // stop playing and tear-down
} else { } else {
if (Record.isRecording) { if (isRecording) {
Record.stopRecording(Record.closeContinueRemove); // stop recording and tear-down Record.stopRecording(Record.closeContinueRemove); // stop recording and tear-down
} else { } else {
Record.closeContinueRemove(); Record.closeContinueRemove();
} }
} }
}; }
Record.tearDownRecorder = function () { static tearDownRecorder () {
// Clear errors // Clear errors
if (Record.error) { if (error) {
Record.error = false; error = false;
} }
// Refresh audio context // Refresh audio context
ScratchAudio.firstTime = true; ScratchAudio.firstTime = true;
Record.isRecording = false; isRecording = false;
Record.recordedSound = null; recordedSound = null;
// Hide the dialog // Hide the dialog
Record.disappear(); Record.disappear();
}; }
// Called when the app is put into the background // Called when the app is put into the background
Record.recordError = function () { static recordError () {
Record.error = true; error = true;
Record.killRecorder(); Record.killRecorder();
}; }
}

View file

@ -1,20 +1,39 @@
var ScriptsPane = function () {};
ScriptsPane.scroll = undefined; import ScratchJr from '../ScratchJr';
import Project from './Project';
import Thumbs from './Thumbs';
import Palette from './Palette';
import Undo from './Undo';
import Events from '../../utils/Events';
import Scroll from './Scroll';
import Menu from './Menu';
import ScratchAudio from '../../utils/ScratchAudio';
import {frame, gn, localx, localy, newHTML, isTablet,
globalx, globaly, setCanvasSize, getDocumentHeight, frame} from '../../utils/lib';
ScriptsPane.watermark; let scroll = undefined;
let watermark;
ScriptsPane.createScripts = function (parent) { export default class ScriptsPane {
static get scroll () {
return scroll;
}
static get watermark () {
return watermark;
}
static createScripts (parent) {
var div = newHTML('div', 'scripts', parent); var div = newHTML('div', 'scripts', parent);
div.setAttribute('id', 'scripts'); div.setAttribute('id', 'scripts');
ScriptsPane.watermark = newHTML('div', 'watermark', div); watermark = newHTML('div', 'watermark', div);
var h = Math.max(getDocumentHeight(), frame.offsetHeight); var h = Math.max(getDocumentHeight(), frame.offsetHeight);
setCanvasSize(div, div.offsetWidth, h - div.offsetTop); setCanvasSize(div, div.offsetWidth, h - div.offsetTop);
ScriptsPane.scroll = new Scroll(div, 'scriptscontainer', div.offsetWidth, scroll = new Scroll(div, 'scriptscontainer', div.offsetWidth,
h - div.offsetTop, ScratchJr.getActiveScript, ScratchJr.getBlocks); h - div.offsetTop, ScratchJr.getActiveScript, ScratchJr.getBlocks);
}; }
ScriptsPane.setActiveScript = function (sprname) { static setActiveScript (sprname) {
var currentsc = gn(sprname + '_scripts'); var currentsc = gn(sprname + '_scripts');
if (!currentsc) { if (!currentsc) {
// Sprite not found // Sprite not found
@ -25,10 +44,10 @@ ScriptsPane.setActiveScript = function (sprname) {
currentsc.parentNode.ontouchstart = function (evt) { currentsc.parentNode.ontouchstart = function (evt) {
currentsc.owner.scriptsMouseDown(evt); currentsc.owner.scriptsMouseDown(evt);
}; };
ScriptsPane.scroll.update(); scroll.update();
}; }
ScriptsPane.runBlock = function (e, div) { static runBlock (e, div) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var b = div.owner.findFirst(); var b = div.owner.findFirst();
@ -39,15 +58,15 @@ ScriptsPane.runBlock = function (e, div) {
ScratchJr.runtime.addRunScript(ScratchJr.getSprite(), b); ScratchJr.runtime.addRunScript(ScratchJr.getSprite(), b);
ScratchJr.startCurrentPageStrips(['ontouch']); ScratchJr.startCurrentPageStrips(['ontouch']);
ScratchJr.userStart = true; ScratchJr.userStart = true;
}; }
ScriptsPane.prepareToDrag = function (e) { static prepareToDrag (e) {
e.preventDefault(); e.preventDefault();
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
ScriptsPane.pickBlock(pt.x, pt.y, e); ScriptsPane.pickBlock(pt.x, pt.y, e);
}; }
ScriptsPane.pickBlock = function (x, y, e) { static pickBlock (x, y, e) {
if (!ScratchJr.runtime.inactive()) { if (!ScratchJr.runtime.inactive()) {
ScratchJr.stopStrips(); ScratchJr.stopStrips();
} }
@ -95,22 +114,22 @@ ScriptsPane.pickBlock = function (x, y, e) {
// b.lift(); // b.lift();
Events.dragcanvas.appendChild(b.div); Events.dragcanvas.appendChild(b.div);
} }
}; }
//////////////////////////////////////////////// ////////////////////////////////////////////////
// Events MouseMove // Events MouseMove
//////////////////////////////////////////////// ////////////////////////////////////////////////
ScriptsPane.draggingBlock = function (e) { static draggingBlock (e) {
e.preventDefault(); e.preventDefault();
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
var dx = pt.x - Events.dragmousex; var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey; var dy = pt.y - Events.dragmousey;
Events.move3D(Events.dragcanvas, dx, dy); Events.move3D(Events.dragcanvas, dx, dy);
ScriptsPane.blockFeedback(Events.dragcanvas.left, Events.dragcanvas.top, e); ScriptsPane.blockFeedback(Events.dragcanvas.left, Events.dragcanvas.top, e);
}; }
ScriptsPane.blockFeedback = function (dx, dy, e) { static blockFeedback (dx, dy, e) {
var script = ScratchJr.getActiveScript().owner; var script = ScratchJr.getActiveScript().owner;
var limit = gn('palette').parentNode.offsetTop + gn('palette').parentNode.offsetHeight; var limit = gn('palette').parentNode.offsetTop + gn('palette').parentNode.offsetHeight;
var ycor = dy + Events.dragcanvas.offsetHeight; var ycor = dy + Events.dragcanvas.offsetHeight;
@ -143,14 +162,14 @@ ScriptsPane.blockFeedback = function (dx, dy, e) {
ScriptsPane.removeLibCaret(); ScriptsPane.removeLibCaret();
break; break;
} }
}; }
//////////////////////////////////////////////// ////////////////////////////////////////////////
// Events MouseUP // Events MouseUP
//////////////////////////////////////////////// ////////////////////////////////////////////////
ScriptsPane.dropBlock = function (e, el) { static dropBlock (e, el) {
e.preventDefault(); e.preventDefault();
var sc = ScratchJr.getActiveScript(); var sc = ScratchJr.getActiveScript();
var spr = sc.owner.spr.id; var spr = sc.owner.spr.id;
@ -183,9 +202,9 @@ ScriptsPane.dropBlock = function (e, el) {
break; break;
default: default:
ScratchJr.getActiveScript().owner.deleteBlocks(); ScratchJr.getActiveScript().owner.deleteBlocks();
ScriptsPane.scroll.adjustCanvas(); scroll.adjustCanvas();
ScriptsPane.scroll.refresh(); scroll.refresh();
ScriptsPane.scroll.fitToScreen(); scroll.fitToScreen();
break; break;
} }
Undo.record({ Undo.record({
@ -194,27 +213,27 @@ ScriptsPane.dropBlock = function (e, el) {
who: spr who: spr
}); });
ScratchJr.getActiveScript().owner.dragList = []; ScratchJr.getActiveScript().owner.dragList = [];
}; }
ScriptsPane.blockDropped = function (sc, dx, dy) { static blockDropped (sc, dx, dy) {
Events.dragcanvas.style.zIndex = ''; Events.dragcanvas.style.zIndex = '';
var script = ScratchJr.getActiveScript().owner; var script = ScratchJr.getActiveScript().owner;
ScriptsPane.cleanCarets(); ScriptsPane.cleanCarets();
script.addBlockToScripts(Events.dragcanvas, dx, dy); script.addBlockToScripts(Events.dragcanvas, dx, dy);
script.layout(Events.dragcanvas.owner); script.layout(Events.dragcanvas.owner);
if (sc.id == ScratchJr.getActiveScript().id) { if (sc.id == ScratchJr.getActiveScript().id) {
ScriptsPane.scroll.adjustCanvas(); scroll.adjustCanvas();
ScriptsPane.scroll.refresh(); scroll.refresh();
ScriptsPane.scroll.bounceBack(); scroll.bounceBack();
}
} }
};
ScriptsPane.cleanCarets = function () { static cleanCarets () {
ScratchJr.getActiveScript().owner.removeCaret(); ScratchJr.getActiveScript().owner.removeCaret();
ScriptsPane.removeLibCaret(); ScriptsPane.removeLibCaret();
}; }
ScriptsPane.removeLibCaret = function () { static removeLibCaret () {
for (var i = 0; i < gn('spritecc').childElementCount; i++) { for (var i = 0; i < gn('spritecc').childElementCount; i++) {
var spr = gn('spritecc').childNodes[i]; var spr = gn('spritecc').childNodes[i];
if (spr.nodeName == 'FORM') { if (spr.nodeName == 'FORM') {
@ -222,13 +241,13 @@ ScriptsPane.removeLibCaret = function () {
} }
Thumbs.quickRestore(spr); Thumbs.quickRestore(spr);
} }
}; }
//---------------------------------- //----------------------------------
// Drag Script Background // Drag Script Background
//---------------------------------- //----------------------------------
ScriptsPane.dragBackground = function (e) { static dragBackground (e) {
if (Menu.openMenu) { if (Menu.openMenu) {
return; return;
} }
@ -245,9 +264,9 @@ ScriptsPane.dragBackground = function (e) {
Events.dragmousey = pt.y; Events.dragmousey = pt.y;
Events.dragged = false; Events.dragged = false;
ScriptsPane.setDragBackgroundEvents(ScriptsPane.dragMove, ScriptsPane.dragEnd); ScriptsPane.setDragBackgroundEvents(ScriptsPane.dragMove, ScriptsPane.dragEnd);
}; }
ScriptsPane.setDragBackgroundEvents = function (fcnmove, fcnup) { static setDragBackgroundEvents (fcnmove, fcnup) {
if (isTablet) { // setDragBackgroundEvents if (isTablet) { // setDragBackgroundEvents
window.ontouchmove = function (evt) { window.ontouchmove = function (evt) {
fcnmove(evt); fcnmove(evt);
@ -263,9 +282,9 @@ ScriptsPane.setDragBackgroundEvents = function (fcnmove, fcnup) {
fcnup(evt); fcnup(evt);
}; };
} }
}; }
ScriptsPane.dragMove = function (e) { static dragMove (e) {
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
if (!Events.dragged && (Events.distance(Events.dragmousex - pt.x, Events.dragmousey - pt.y) < 5)) { if (!Events.dragged && (Events.distance(Events.dragmousex - pt.x, Events.dragmousey - pt.y) < 5)) {
return; return;
@ -276,22 +295,22 @@ ScriptsPane.dragMove = function (e) {
Events.dragmousex = pt.x; Events.dragmousex = pt.x;
Events.dragmousey = pt.y; Events.dragmousey = pt.y;
Events.move3D(ScratchJr.getActiveScript(), dx, dy); Events.move3D(ScratchJr.getActiveScript(), dx, dy);
ScriptsPane.scroll.refresh(); scroll.refresh();
e.preventDefault(); e.preventDefault();
}; }
ScriptsPane.dragEnd = function (e) { static dragEnd (e) {
Events.dragged = false; Events.dragged = false;
e.preventDefault(); e.preventDefault();
Events.clearEvents(); Events.clearEvents();
ScriptsPane.scroll.bounceBack(); scroll.bounceBack();
}; }
////////////////////// //////////////////////
// //
////////////////////// //////////////////////
ScriptsPane.updateScriptsPageBlocks = function (list) { static updateScriptsPageBlocks (list) {
for (var j = 0; j < list.length; j++) { for (var j = 0; j < list.length; j++) {
if (!gn(list[j] + '_scripts')) { if (!gn(list[j] + '_scripts')) {
continue; continue;
@ -305,4 +324,5 @@ ScriptsPane.updateScriptsPageBlocks = function (list) {
allblocks[i].updateBlock(); allblocks[i].updateBlock();
} }
} }
}; }
}

View file

@ -2,10 +2,21 @@
// Pages // Pages
///////////////////////////////////// /////////////////////////////////////
Thumbs = function () {}; import ScratchJr from '../ScratchJr';
Thumbs.caret = undefined; import Palette from './Palette';
import Page from './Page';
import ScriptsPane from './ScriptsPane';
import Undo from './Undo';
import UI from './UI';
import Events from '../../utils/Events';
import ScratchAudio from '../../utils/ScratchAudio';
import {frame, gn, localx, newHTML, scaleMultiplier, getIdFor,
isTablet, newImage, localy, setProps} from '../../utils/lib';
Thumbs.updatePages = function () { let caret = undefined;
export default class Thumbs {
static updatePages () {
var pthumbs = gn('pagecc'); var pthumbs = gn('pagecc');
while (pthumbs.childElementCount > 0) { while (pthumbs.childElementCount > 0) {
pthumbs.removeChild(pthumbs.childNodes[0]); pthumbs.removeChild(pthumbs.childNodes[0]);
@ -33,18 +44,18 @@ Thumbs.updatePages = function () {
var ep = Thumbs.emptyPage(pthumbs); var ep = Thumbs.emptyPage(pthumbs);
ep.prev = prev; ep.prev = prev;
th.next = ep; th.next = ep;
}; }
Thumbs.getObjectFor = function (div, id) { static getObjectFor (div, id) {
for (var i = 0; i < div.childElementCount; i++) { for (var i = 0; i < div.childElementCount; i++) {
if (div.childNodes[i].owner == id) { if (div.childNodes[i].owner == id) {
return div.childNodes[i]; return div.childNodes[i];
} }
} }
return div.childNodes[0]; return div.childNodes[0];
}; }
Thumbs.getType = function (div, str) { static getType (div, str) {
while (div != null) { while (div != null) {
if (div.type == str) { if (div.type == str) {
return div; return div;
@ -52,9 +63,9 @@ Thumbs.getType = function (div, str) {
div = div.parentNode; div = div.parentNode;
} }
return null; return null;
}; }
Thumbs.pageMouseDown = function (e) { static pageMouseDown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -87,9 +98,9 @@ Thumbs.pageMouseDown = function (e) {
Events.startDrag(e, tb, Thumbs.prepareToDragPage, Thumbs.dropPage, Thumbs.draggingPage, Events.startDrag(e, tb, Thumbs.prepareToDragPage, Thumbs.dropPage, Thumbs.draggingPage,
Thumbs.clickPage, Thumbs.startPageShaking); Thumbs.clickPage, Thumbs.startPageShaking);
} }
}; }
Thumbs.prepareToDragPage = function (e) { static prepareToDragPage (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
ScratchAudio.sndFX('grab.wav'); ScratchAudio.sndFX('grab.wav');
@ -108,45 +119,45 @@ Thumbs.prepareToDragPage = function (e) {
setProps(Events.dragcanvas.style, mstyle); setProps(Events.dragcanvas.style, mstyle);
Events.move3D(Events.dragcanvas, mx, my); Events.move3D(Events.dragcanvas, mx, my);
frame.appendChild(Events.dragcanvas); frame.appendChild(Events.dragcanvas);
Thumbs.caret = newHTML('div', 'pagethumb caret', gn('pagecc')); caret = newHTML('div', 'pagethumb caret', gn('pagecc'));
Thumbs.caret.prev = Events.dragthumbnail.prev; caret.prev = Events.dragthumbnail.prev;
Thumbs.caret.next = Events.dragthumbnail.next; caret.next = Events.dragthumbnail.next;
if (Events.dragthumbnail.prev) { if (Events.dragthumbnail.prev) {
(Events.dragthumbnail.prev).next = Thumbs.caret; (Events.dragthumbnail.prev).next = caret;
} }
if (Events.dragthumbnail.next) { if (Events.dragthumbnail.next) {
(Events.dragthumbnail.next).prev = Thumbs.caret; (Events.dragthumbnail.next).prev = caret;
} }
Thumbs.layoutPages(); Thumbs.layoutPages();
Events.dragthumbnail.pos = Thumbs.getPagePos(Events.dragcanvas.top); Events.dragthumbnail.pos = Thumbs.getPagePos(Events.dragcanvas.top);
}; }
Thumbs.layoutPages = function () { static layoutPages () {
var thispage = Thumbs.findFirst(); var thispage = Thumbs.findFirst();
var p = gn('pagecc'); var p = gn('pagecc');
while (thispage) { while (thispage) {
p.appendChild(thispage); p.appendChild(thispage);
thispage = thispage.next; thispage = thispage.next;
} }
}; }
Thumbs.findFirst = function () { static findFirst () {
var kid = gn('pagecc').childNodes[0]; var kid = gn('pagecc').childNodes[0];
while (kid.prev) { while (kid.prev) {
kid = kid.prev; kid = kid.prev;
} }
return kid; return kid;
}; }
Thumbs.findLast = function () { static findLast () {
var kid = gn('pagecc').childNodes[0]; var kid = gn('pagecc').childNodes[0];
while (kid.next) { while (kid.next) {
kid = kid.next; kid = kid.next;
} }
return kid; return kid;
}; }
Thumbs.getPageOrder = function () { static getPageOrder () {
var page = Thumbs.findFirst(); var page = Thumbs.findFirst();
var res = []; var res = [];
while (page) { while (page) {
@ -157,54 +168,54 @@ Thumbs.getPageOrder = function () {
page = page.next; page = page.next;
} }
return res; return res;
}; }
Thumbs.draggingPage = function (e, el) { static draggingPage (e, el) {
e.preventDefault(); e.preventDefault();
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
var dx = pt.x - Events.dragmousex; var dx = pt.x - Events.dragmousex;
var dy = pt.y - Events.dragmousey; var dy = pt.y - Events.dragmousey;
Events.move3D(el, dx, dy); Events.move3D(el, dx, dy);
if (!Thumbs.caret) { if (!caret) {
return; return;
} }
Thumbs.removeCaret(); Thumbs.removeCaret();
Thumbs.insertCaret(el); Thumbs.insertCaret(el);
Thumbs.layoutPages(); Thumbs.layoutPages();
}; }
Thumbs.removeCaret = function () { static removeCaret () {
var myprev = Thumbs.caret.prev; var myprev = caret.prev;
var mynext = Thumbs.caret.next; var mynext = caret.next;
if (myprev) { if (myprev) {
myprev.next = mynext; myprev.next = mynext;
} }
if (mynext) { if (mynext) {
mynext.prev = myprev; mynext.prev = myprev;
} }
Thumbs.caret.prev = undefined; caret.prev = undefined;
Thumbs.caret.next = undefined; caret.next = undefined;
var p = Thumbs.caret.parentNode; var p = caret.parentNode;
if (p) { if (p) {
p.removeChild(Thumbs.caret); p.removeChild(caret);
}
} }
};
Thumbs.insertCaret = function (el) { static insertCaret (el) {
var pos = Thumbs.getPagePos(el.top); var pos = Thumbs.getPagePos(el.top);
Thumbs.positionMe(pos, Thumbs.caret); Thumbs.positionMe(pos, caret);
gn('pagecc').appendChild(Thumbs.caret); gn('pagecc').appendChild(caret);
}; }
Thumbs.getPagePos = function (dy) { static getPagePos (dy) {
var delta = gn('pagecc').childNodes[1].offsetTop - gn('pagecc').childNodes[0].offsetTop; var delta = gn('pagecc').childNodes[1].offsetTop - gn('pagecc').childNodes[0].offsetTop;
var pos = Math.floor(localy(gn('pagecc'), dy + (delta / 2)) / delta); var pos = Math.floor(localy(gn('pagecc'), dy + (delta / 2)) / delta);
pos = Math.max(0, pos); pos = Math.max(0, pos);
var max = Thumbs.getPageOrder().length; var max = Thumbs.getPageOrder().length;
return Math.min(max, pos); return Math.min(max, pos);
}; }
Thumbs.positionMe = function (pos, elem) { static positionMe (pos, elem) {
var beforewho = pos >= gn('pagecc').childElementCount ? undefined : gn('pagecc').childNodes[pos]; var beforewho = pos >= gn('pagecc').childElementCount ? undefined : gn('pagecc').childNodes[pos];
if (!beforewho) { if (!beforewho) {
var last = Thumbs.findLast(); var last = Thumbs.findLast();
@ -220,9 +231,9 @@ Thumbs.positionMe = function (pos, elem) {
elem.prev = prev; elem.prev = prev;
} }
} }
}; }
Thumbs.repositionThumb = function (thumb, dy) { static repositionThumb (thumb, dy) {
var pos = Thumbs.getPagePos(dy); var pos = Thumbs.getPagePos(dy);
if (pos != thumb.pos) { if (pos != thumb.pos) {
ScratchAudio.sndFX('snap.wav'); ScratchAudio.sndFX('snap.wav');
@ -236,26 +247,26 @@ Thumbs.repositionThumb = function (thumb, dy) {
mynext.prev = myprev; mynext.prev = myprev;
} }
Thumbs.positionMe(pos, thumb); Thumbs.positionMe(pos, thumb);
}; }
Thumbs.dropPage = function (e) { static dropPage (e) {
ScratchJr.storyStart('Thumbs.dropPage'); ScratchJr.storyStart('Thumbs.dropPage');
e.preventDefault(); e.preventDefault();
if (!Thumbs.caret) { if (!caret) {
return; return;
} }
Events.dragthumbnail.prev = Thumbs.caret.prev; Events.dragthumbnail.prev = caret.prev;
Events.dragthumbnail.next = Thumbs.caret.next; Events.dragthumbnail.next = caret.next;
if (Events.dragthumbnail.prev) { if (Events.dragthumbnail.prev) {
(Events.dragthumbnail.prev).next = Events.dragthumbnail; (Events.dragthumbnail.prev).next = Events.dragthumbnail;
} }
if (Events.dragthumbnail.next) { if (Events.dragthumbnail.next) {
(Events.dragthumbnail.next).prev = Events.dragthumbnail; (Events.dragthumbnail.next).prev = Events.dragthumbnail;
} }
if (Thumbs.caret.parentNode) { if (caret.parentNode) {
Thumbs.caret.parentNode.removeChild(Thumbs.caret); caret.parentNode.removeChild(caret);
} }
Thumbs.caret = undefined; caret = undefined;
Events.dragthumbnail.style.position = ''; Events.dragthumbnail.style.position = '';
Events.dragthumbnail.style.left = ''; Events.dragthumbnail.style.left = '';
Events.dragthumbnail.style.top = ''; Events.dragthumbnail.style.top = '';
@ -278,16 +289,16 @@ Thumbs.dropPage = function (e) {
where: oldpage where: oldpage
}); });
} }
}; }
Thumbs.clickPage = function (e) { static clickPage (e) {
ScratchJr.clearSelection(); ScratchJr.clearSelection();
Thumbs.clickOnPage(e, Events.dragthumbnail.owner); Thumbs.clickOnPage(e, Events.dragthumbnail.owner);
Events.clearEvents(); Events.clearEvents();
Events.dragthumbnail = undefined; Events.dragthumbnail = undefined;
}; }
Thumbs.clickOnPage = function (e, pagename) { static clickOnPage (e, pagename) {
ScratchJr.unfocus(e); ScratchJr.unfocus(e);
var pthumbs = gn('pagecc'); var pthumbs = gn('pagecc');
for (var i = 0; i < pthumbs.childElementCount; i++) { for (var i = 0; i < pthumbs.childElementCount; i++) {
@ -306,28 +317,28 @@ Thumbs.clickOnPage = function (e, pagename) {
who: pagename, who: pagename,
where: pagename where: pagename
}); });
}; }
Thumbs.startPageShaking = function (tb) { static startPageShaking (tb) {
ScratchJr.shaking = tb; ScratchJr.shaking = tb;
ScratchJr.stopShaking = Thumbs.stopPageShaking; ScratchJr.stopShaking = Thumbs.stopPageShaking;
var cc = tb.getAttribute('class'); var cc = tb.getAttribute('class');
tb.setAttribute('class', cc + ' shakeme'); tb.setAttribute('class', cc + ' shakeme');
tb.childNodes[tb.childElementCount - 1].style.visibility = 'visible'; tb.childNodes[tb.childElementCount - 1].style.visibility = 'visible';
}; }
Thumbs.stopPageShaking = function (b) { static stopPageShaking (b) {
ScratchJr.shaking = undefined; ScratchJr.shaking = undefined;
ScratchJr.stopShaking = undefined; ScratchJr.stopShaking = undefined;
var cc = b.getAttribute('class'); var cc = b.getAttribute('class');
cc = cc.substr(0, cc.length - 8); cc = cc.substr(0, cc.length - 8);
b.setAttribute('class', cc); b.setAttribute('class', cc);
b.childNodes[b.childElementCount - 1].style.visibility = 'hidden'; b.childNodes[b.childElementCount - 1].style.visibility = 'hidden';
}; }
Thumbs.emptyPage = function (p) { static emptyPage (p) {
var tb = newHTML('div', 'pagethumb', p); var tb = newHTML('div', 'pagethumb', p);
var c = newHTML('div', 'empty', tb); var c = newHTML('div', 'empty', tb);
var img; var img;
@ -350,9 +361,9 @@ Thumbs.emptyPage = function (p) {
}; };
} }
return tb; return tb;
}; }
Thumbs.clickOnEmptyPage = function (e) { static clickOnEmptyPage (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -366,25 +377,25 @@ Thumbs.clickOnEmptyPage = function (e) {
} }
ScratchJr.unfocus(e); ScratchJr.unfocus(e);
new Page(getIdFor('page')); new Page(getIdFor('page'));
}; }
Thumbs.highlighPage = function (page) { static highlighPage (page) {
page.setAttribute('class', 'pagethumb on'); page.setAttribute('class', 'pagethumb on');
}; }
Thumbs.unhighlighPage = function (page) { static unhighlighPage (page) {
page.setAttribute('class', 'pagethumb off'); page.setAttribute('class', 'pagethumb off');
}; }
Thumbs.overpage = function (page) { static overpage (page) {
page.setAttribute('class', 'pagethumb drop'); page.setAttribute('class', 'pagethumb drop');
}; }
////////////////////////////////////// //////////////////////////////////////
// Library // Library
///////////////////////////////////// /////////////////////////////////////
Thumbs.updateSprites = function () { static updateSprites () {
var costumes = gn('spritecc'); var costumes = gn('spritecc');
costumes.style.top = '0px'; costumes.style.top = '0px';
while (costumes.childElementCount > 0) { while (costumes.childElementCount > 0) {
@ -411,9 +422,9 @@ Thumbs.updateSprites = function () {
ScratchJr.stage.currentPage.setCurrentSprite(undefined); ScratchJr.stage.currentPage.setCurrentSprite(undefined);
} }
UI.resetSpriteLibrary(); UI.resetSpriteLibrary();
}; }
Thumbs.updateSprite = function (spr) { static updateSprite (spr) {
if (!spr) { if (!spr) {
return; return;
} }
@ -428,13 +439,13 @@ Thumbs.updateSprite = function (spr) {
Thumbs.selectThisSprite(spr); Thumbs.selectThisSprite(spr);
UI.resetSpriteLibrary(); UI.resetSpriteLibrary();
} }
}; }
///////////////////////////////////////////// /////////////////////////////////////////////
// Sprite Thumbnails // Sprite Thumbnails
//////////////////////////////////////////// ////////////////////////////////////////////
Thumbs.startDragThumb = function (e, tb) { static startDragThumb (e, tb) {
if (ScratchJr.shaking && (e.target.id == 'deletespritethumb')) { if (ScratchJr.shaking && (e.target.id == 'deletespritethumb')) {
ScratchJr.clearSelection(); ScratchJr.clearSelection();
ScratchJr.stage.removeSprite(gn(tb.owner).owner); ScratchJr.stage.removeSprite(gn(tb.owner).owner);
@ -448,9 +459,9 @@ Thumbs.startDragThumb = function (e, tb) {
Events.startDrag(e, tb, Thumbs.prepareToDrag, Thumbs.drop, Events.startDrag(e, tb, Thumbs.prepareToDrag, Thumbs.drop,
Thumbs.dragging, Thumbs.click, Thumbs.startCharShaking); Thumbs.dragging, Thumbs.click, Thumbs.startCharShaking);
} }
}; }
Thumbs.startCharShaking = function (tb) { static startCharShaking (tb) {
if (!tb) { if (!tb) {
return; return;
} }
@ -460,9 +471,9 @@ Thumbs.startCharShaking = function (tb) {
tb.setAttribute('class', cc + ' shakethumb'); tb.setAttribute('class', cc + ' shakethumb');
var close = newHTML('div', 'deletespritethumb', tb); var close = newHTML('div', 'deletespritethumb', tb);
close.id = 'deletespritethumb'; close.id = 'deletespritethumb';
}; }
Thumbs.stopCharShaking = function (b) { static stopCharShaking (b) {
ScratchJr.shaking = undefined; ScratchJr.shaking = undefined;
ScratchJr.stopShaking = undefined; ScratchJr.stopShaking = undefined;
var cc = b.getAttribute('class'); var cc = b.getAttribute('class');
@ -472,9 +483,9 @@ Thumbs.stopCharShaking = function (b) {
if (ic.getAttribute('class') == 'deletespritethumb') { if (ic.getAttribute('class') == 'deletespritethumb') {
b.removeChild(ic); b.removeChild(ic);
} }
}; }
Thumbs.selectThisSprite = function (spr) { static selectThisSprite (spr) {
var costumes = gn('spritecc'); var costumes = gn('spritecc');
var el = spr.thumbnail; var el = spr.thumbnail;
for (var i = 0; i < costumes.childElementCount; i++) { for (var i = 0; i < costumes.childElementCount; i++) {
@ -485,9 +496,9 @@ Thumbs.selectThisSprite = function (spr) {
Thumbs.unhighlighSprite(th); Thumbs.unhighlighSprite(th);
} }
} }
}; }
Thumbs.clickOnSprite = function (e, el) { static clickOnSprite (e, el) {
if (ScratchJr.shaking && (ScratchJr.shaking == el)) { if (ScratchJr.shaking && (ScratchJr.shaking == el)) {
ScratchJr.clearSelection(); ScratchJr.clearSelection();
ScratchJr.stage.removeSprite(gn(el.owner).owner); ScratchJr.stage.removeSprite(gn(el.owner).owner);
@ -502,9 +513,9 @@ Thumbs.clickOnSprite = function (e, el) {
var page = spr.div.parentNode.owner; var page = spr.div.parentNode.owner;
page.setCurrentSprite(spr); page.setCurrentSprite(spr);
Thumbs.selectThisSprite(spr); Thumbs.selectThisSprite(spr);
}; }
Thumbs.prepareToDrag = function (e) { static prepareToDrag (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
ScratchAudio.sndFX('grab.wav'); ScratchAudio.sndFX('grab.wav');
@ -537,9 +548,9 @@ Thumbs.prepareToDrag = function (e) {
Events.move3D(Events.dragcanvas, mx * window.devicePixelRatio, my * window.devicePixelRatio); Events.move3D(Events.dragcanvas, mx * window.devicePixelRatio, my * window.devicePixelRatio);
Events.dragcanvas.owner = Events.dragthumbnail.owner; Events.dragcanvas.owner = Events.dragthumbnail.owner;
frame.appendChild(Events.dragcanvas); frame.appendChild(Events.dragcanvas);
}; }
Thumbs.dragging = function (e, el) { static dragging (e, el) {
e.preventDefault(); e.preventDefault();
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
var dx = pt.x - Events.dragmousex; var dx = pt.x - Events.dragmousex;
@ -570,9 +581,9 @@ Thumbs.dragging = function (e, el) {
} }
} }
} }
}; }
Thumbs.removePagesCaret = function () { static removePagesCaret () {
for (var i = 0; i < gn('pagecc').childElementCount; i++) { for (var i = 0; i < gn('pagecc').childElementCount; i++) {
var spr = gn('pagecc').childNodes[i]; var spr = gn('pagecc').childNodes[i];
if (!spr.owner) { if (!spr.owner) {
@ -585,9 +596,9 @@ Thumbs.removePagesCaret = function () {
Thumbs.unhighlighPage(spr); Thumbs.unhighlighPage(spr);
} }
} }
}; }
Thumbs.drop = function (e, el) { static drop (e, el) {
e.preventDefault(); e.preventDefault();
switch (Palette.getLandingPlace(el, e, window.devicePixelRatio)) { switch (Palette.getLandingPlace(el, e, window.devicePixelRatio)) {
case 'pages': case 'pages':
@ -603,9 +614,9 @@ Thumbs.drop = function (e, el) {
Events.dragcanvas.parentNode.removeChild(Events.dragcanvas); Events.dragcanvas.parentNode.removeChild(Events.dragcanvas);
} }
Events.dragcanvas = undefined; Events.dragcanvas = undefined;
}; }
Thumbs.click = function (e, el) { static click (e, el) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (window.event) { if (window.event) {
@ -615,15 +626,15 @@ Thumbs.click = function (e, el) {
} }
el.setAttribute('class', ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable'); el.setAttribute('class', ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable');
Thumbs.clickOnSprite(e, el); Thumbs.clickOnSprite(e, el);
}; }
Thumbs.highlighSprite = function (spr) { static highlighSprite (spr) {
spr.setAttribute('class', ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable'); spr.setAttribute('class', ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable');
ScriptsPane.setActiveScript(spr.owner); ScriptsPane.setActiveScript(spr.owner);
Palette.reset(); Palette.reset();
}; }
Thumbs.unhighlighSprite = function (spr) { static unhighlighSprite (spr) {
spr.setAttribute('class', 'spritethumb off'); spr.setAttribute('class', 'spritethumb off');
var currentsc = gn(spr.owner + '_scripts'); var currentsc = gn(spr.owner + '_scripts');
currentsc.owner.deactivate(); currentsc.owner.deactivate();
@ -632,20 +643,21 @@ Thumbs.unhighlighSprite = function (spr) {
currentsc.childNodes[i].owner.unhighlight(); currentsc.childNodes[i].owner.unhighlight();
} }
} }
}; }
Thumbs.quickHighlight = function (spr) { static quickHighlight (spr) {
if (spr.owner == ScratchJr.stage.currentPage.currentSpriteName) { if (spr.owner == ScratchJr.stage.currentPage.currentSpriteName) {
spr.className = 'spritethumb on target'; spr.className = 'spritethumb on target';
} else { } else {
spr.className = 'spritethumb off target'; spr.className = 'spritethumb off target';
} }
}; }
Thumbs.quickRestore = function (spr) { static quickRestore (spr) {
if (spr.owner == ScratchJr.stage.currentPage.currentSpriteName) { if (spr.owner == ScratchJr.stage.currentPage.currentSpriteName) {
spr.className = ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable'; spr.className = ScratchJr.isEditable() ? 'spritethumb on' : 'spritethumb noneditable';
} else { } else {
spr.className = 'spritethumb off'; spr.className = 'spritethumb off';
} }
}; }
}

View file

@ -2,14 +2,32 @@
// General UI Layout // General UI Layout
///////////////////////////////////// /////////////////////////////////////
UI = function () {}; import ScratchJr from '../ScratchJr';
import BlockSpecs from '../blocks/BlockSpecs';
import Alert from './Alert';
import Project from './Project';
import Thumbs from './Thumbs';
import Palette from './Palette';
import Grid from './Grid';
import Stage from './Stage';
import ScriptsPane from './ScriptsPane';
import Undo from './Undo';
import Library from './Library';
import iOS from '../../iPad/iOS';
import IO from '../../iPad/IO';
import Paint from '../../painteditor/Paint';
import Events from '../../utils/Events';
import Localization from '../../utils/Localization';
import ScratchAudio from '../../utils/ScratchAudio';
import {frame, gn, CSSTransition, localx, newHTML, scaleMultiplier, getIdFor, isTablet, newDiv,
newTextInput, isAndroid, getDocumentWidth, getDocumentHeight, setProps, globalx} from '../../utils/lib';
UI.projectNameTextInput = null; let projectNameTextInput = null;
UI.info = null; let info = null;
UI.okclicky = null; let okclicky = null;
UI.isAndroid = isAndroid;
UI.layout = function () { export default class UI {
static layout () {
UI.topSection(); UI.topSection();
UI.middleSection(); UI.middleSection();
UI.BottomSection(); UI.BottomSection();
@ -18,11 +36,11 @@ UI.layout = function () {
ScratchJr.setupKeypad(); ScratchJr.setupKeypad();
ScratchJr.setupEditableField(); ScratchJr.setupEditableField();
UI.aspectRatioAdjustment(); UI.aspectRatioAdjustment();
}; }
// Helps debug on Android 4.2 by enabling the user to type in a // Helps debug on Android 4.2 by enabling the user to type in a
// JavaScript expression and evaluate the output and render to console.log. // JavaScript expression and evaluate the output and render to console.log.
/*UI.addDebugControl = function () { /*static addDebugControl () {
var div = newHTML('div', 'debug', document.body); var div = newHTML('div', 'debug', document.body);
setProps(div.style, { setProps(div.style, {
position: 'absolute', position: 'absolute',
@ -36,19 +54,19 @@ UI.layout = function () {
div.ontouchstart = function (e) { div.ontouchstart = function (e) {
console.log(eval(prompt('Enter Debug JavaScript'))); console.log(eval(prompt('Enter Debug JavaScript')));
}; };
};*/ }*/
/** Tweak some elements depending on aspect ratio */ /** Tweak some elements depending on aspect ratio */
UI.aspectRatioAdjustment = function () { static aspectRatioAdjustment () {
var aspect = window.getDocumentWidth() / window.getDocumentHeight(); var aspect = window.getDocumentWidth() / window.getDocumentHeight();
if (aspect > 1.45) { if (aspect > 1.45) {
// Nudge sprite list right a bit and the pages list left a bit // Nudge sprite list right a bit and the pages list left a bit
gn('library').style.left = '3vw'; gn('library').style.left = '3vw';
gn('pages').style.right = '1vw'; gn('pages').style.right = '1vw';
} }
}; }
UI.topSection = function () { static topSection () {
var div = newHTML('div', 'topsection', frame); var div = newHTML('div', 'topsection', frame);
div.setAttribute('id', 'topsection'); div.setAttribute('id', 'topsection');
if (ScratchJr.isEditable()) { if (ScratchJr.isEditable()) {
@ -57,9 +75,9 @@ UI.topSection = function () {
UI.leftPanel(div); UI.leftPanel(div);
UI.stageArea(div); UI.stageArea(div);
UI.rightPanel(div); UI.rightPanel(div);
}; }
UI.leftPanel = function (div) { static leftPanel (div) {
// sprite library // sprite library
var sl = newHTML('div', 'leftpanel', div); var sl = newHTML('div', 'leftpanel', div);
var flip = newHTML('div', 'flipme', sl); var flip = newHTML('div', 'flipme', sl);
@ -68,25 +86,25 @@ UI.leftPanel = function (div) {
ScratchJr.saveAndFlip(evt); ScratchJr.saveAndFlip(evt);
}; // move to project }; // move to project
UI.layoutLibrary(sl); UI.layoutLibrary(sl);
}; }
UI.middleSection = function () { static middleSection () {
var bp = newHTML('div', 'blockspalette', frame); var bp = newHTML('div', 'blockspalette', frame);
bp.setAttribute('id', 'blockspalette'); bp.setAttribute('id', 'blockspalette');
Palette.setup(bp); Palette.setup(bp);
Undo.setup(bp); Undo.setup(bp);
}; }
UI.BottomSection = function () { static BottomSection () {
ScriptsPane.createScripts(frame); ScriptsPane.createScripts(frame);
}; }
UI.addProjectInfo = function () { static addProjectInfo () {
UI.info = newHTML('div', 'info', frame); info = newHTML('div', 'info', frame);
UI.info.setAttribute('id', 'projectinfo'); info.setAttribute('id', 'projectinfo');
var infobox = newHTML('div', 'infobox fade', frame); var infobox = newHTML('div', 'infobox fade', frame);
infobox.setAttribute('id', 'infobox'); infobox.setAttribute('id', 'infobox');
UI.okclicky = newHTML('div', 'paintdone', infobox); okclicky = newHTML('div', 'paintdone', infobox);
newHTML('div', 'infoboxlogo', infobox); newHTML('div', 'infoboxlogo', infobox);
var nameField = UI.addEditableName(infobox); var nameField = UI.addEditableName(infobox);
var staticinfo = newHTML('div', 'fixedinfo', infobox); var staticinfo = newHTML('div', 'fixedinfo', infobox);
@ -101,13 +119,13 @@ UI.addProjectInfo = function () {
shareEmail.id = 'infoboxShareButtonEmail'; shareEmail.id = 'infoboxShareButtonEmail';
shareEmail.textContent = Localization.localize('SHARING_BY_EMAIL'); shareEmail.textContent = Localization.localize('SHARING_BY_EMAIL');
if (UI.isAndroid) { if (isAndroid) {
shareEmail.style.margin = 'auto'; shareEmail.style.margin = 'auto';
} else { } else {
shareEmail.style.float = 'left'; shareEmail.style.float = 'left';
} }
if (!UI.isAndroid) { if (!isAndroid) {
var shareAirdrop = newHTML('div', 'infoboxShareButton', shareButtons); var shareAirdrop = newHTML('div', 'infoboxShareButton', shareButtons);
shareAirdrop.id = 'infoboxShareButtonAirdrop'; shareAirdrop.id = 'infoboxShareButtonAirdrop';
shareAirdrop.textContent = Localization.localize('SHARING_BY_AIRDROP'); shareAirdrop.textContent = Localization.localize('SHARING_BY_AIRDROP');
@ -133,14 +151,14 @@ UI.addProjectInfo = function () {
}; };
} }
UI.info.ontouchend = UI.showInfoBox; info.ontouchend = UI.showInfoBox;
UI.okclicky.ontouchstart = UI.hideInfoBox; okclicky.ontouchstart = UI.hideInfoBox;
UI.okclicky.ontouchstart = function (evt) { okclicky.ontouchstart = function (evt) {
UI.hideInfoBox(evt, nameField); UI.hideInfoBox(evt, nameField);
}; };
}; }
UI.parentalGate = function (evt, callback) { static parentalGate (evt, callback) {
ScratchAudio.sndFX('tap.wav'); ScratchAudio.sndFX('tap.wav');
var pgFrame = newHTML('div', 'parentalgate', gn('frame')); var pgFrame = newHTML('div', 'parentalgate', gn('frame'));
@ -197,20 +215,18 @@ UI.parentalGate = function (evt, callback) {
callback(evt); callback(evt);
} }
} }
}; }
/* /*
+ Save the project, including the new name, then package the project and send native-side for sharing + Save the project, including the new name, then package the project and send native-side for sharing
+ +
+ evt: reference to touch event triggering share + evt: reference to touch event triggering share
+ nameField: reference to the project rename field + nameField: reference to the project rename field
+ shareLoadingGif: reference to HTML element to show during packaging/loading and hide for completion + shareLoadingGif: reference to HTML element to show during packaging/loading and hide for completion
+ shareType: which dialog to show - 0 for email; 1 for airdrop + shareType: which dialog to show - 0 for email; 1 for airdrop
+ */ + */
UI.shareBody = Localization.localize('SHARING_EMAIL_TEXT'); static infoDoShare (evt, nameField, shareLoadingGif, shareType) {
UI.infoDoShare = function (evt, nameField, shareLoadingGif, shareType) {
ScratchAudio.sndFX('tap.wav'); ScratchAudio.sndFX('tap.wav');
shareLoadingGif.style.visibility = 'visible'; shareLoadingGif.style.visibility = 'visible';
nameField.blur(); // Hide the keyboard for name changes nameField.blur(); // Hide the keyboard for name changes
@ -236,16 +252,17 @@ UI.infoDoShare = function (evt, nameField, shareLoadingGif, shareType) {
var emailSubject = Localization.localize('SHARING_EMAIL_SUBJECT', { var emailSubject = Localization.localize('SHARING_EMAIL_SUBJECT', {
PROJECT_NAME: IO.shareName PROJECT_NAME: IO.shareName
}); });
iOS.sendSjrToShareDialog(IO.zipFileName, emailSubject, UI.shareBody, shareType, contents); iOS.sendSjrToShareDialog(IO.zipFileName, emailSubject, Localization.localize('SHARING_EMAIL_TEXT'),
shareType, contents);
shareLoadingGif.style.visibility = 'hidden'; shareLoadingGif.style.visibility = 'hidden';
}); });
}); });
} }
}; }
UI.addEditableName = function (p) { static addEditableName (p) {
var pname = newHTML('form', 'projectname', p); var pname = newHTML('form', 'projectname', p);
pname.name = 'projectname'; pname.name = 'projectname';
pname.id = 'title'; pname.id = 'title';
@ -253,7 +270,7 @@ UI.addEditableName = function (p) {
submitChange(evt); submitChange(evt);
}; };
var ti = newHTML('input', 'pnamefield', pname); var ti = newHTML('input', 'pnamefield', pname);
UI.projectNameTextInput = ti; projectNameTextInput = ti;
ti.name = 'myproject'; ti.name = 'myproject';
ti.maxLength = 30; ti.maxLength = 30;
ti.onkeypress = undefined; ti.onkeypress = undefined;
@ -263,7 +280,7 @@ UI.addEditableName = function (p) {
ti.onfocus = function (e) { ti.onfocus = function (e) {
e.preventDefault(); e.preventDefault();
ti.oldvalue = ti.value; ti.oldvalue = ti.value;
if (UI.isAndroid) { if (isAndroid) {
AndroidInterface.scratchjr_setsoftkeyboardscrolllocation( AndroidInterface.scratchjr_setsoftkeyboardscrolllocation(
ti.getBoundingClientRect().top * window.devicePixelRatio, ti.getBoundingClientRect().top * window.devicePixelRatio,
ti.getBoundingClientRect().bottom * window.devicePixelRatio ti.getBoundingClientRect().bottom * window.devicePixelRatio
@ -286,9 +303,9 @@ UI.addEditableName = function (p) {
input.blur(); input.blur();
} }
return ti; return ti;
}; }
UI.handleTextFieldSave = function (dontHide) { static handleTextFieldSave (dontHide) {
// Handle story-starter mode project // Handle story-starter mode project
if (ScratchJr.isEditable() && ScratchJr.editmode == 'storyStarter' && !Project.error) { if (ScratchJr.isEditable() && ScratchJr.editmode == 'storyStarter' && !Project.error) {
iOS.analyticsEvent('samples', 'story_starter_edited', Project.metadata.name); iOS.analyticsEvent('samples', 'story_starter_edited', Project.metadata.name);
@ -314,10 +331,10 @@ UI.handleTextFieldSave = function (dontHide) {
} else { } else {
UI.finishTextFieldSave(dontHide); UI.finishTextFieldSave(dontHide);
} }
}; }
UI.finishTextFieldSave = function (dontHide) { static finishTextFieldSave (dontHide) {
var ti = UI.projectNameTextInput; var ti = projectNameTextInput;
var pname = (ti.value.length == 0) ? ti.oldvalue : ti.value.substring(0, ti.maxLength); var pname = (ti.value.length == 0) ? ti.oldvalue : ti.value.substring(0, ti.maxLength);
if (Project.metadata.name != pname) { if (Project.metadata.name != pname) {
ScratchJr.storyStart('UI.handleTextFieldSave'); ScratchJr.storyStart('UI.handleTextFieldSave');
@ -329,9 +346,9 @@ UI.finishTextFieldSave = function (dontHide) {
ScratchAudio.sndFX('exittap.wav'); ScratchAudio.sndFX('exittap.wav');
gn('infobox').className = 'infobox fade'; gn('infobox').className = 'infobox fade';
} }
}; }
UI.showInfoBox = function (e) { static showInfoBox (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (Paint.saving) { if (Paint.saving) {
@ -343,19 +360,19 @@ UI.showInfoBox = function (e) {
// Prevent button from thrashing // Prevent button from thrashing
setTimeout(function () { setTimeout(function () {
UI.okclicky.ontouchend = UI.hideInfoBox; okclicky.ontouchend = UI.hideInfoBox;
UI.projectNameTextInput.onblur = function () { projectNameTextInput.onblur = function () {
if (UI.isAndroid) { if (isAndroid) {
AndroidInterface.scratchjr_forceHideKeyboard(); AndroidInterface.scratchjr_forceHideKeyboard();
} }
}; };
}, 500); }, 500);
UI.projectNameTextInput.onblur = function () { projectNameTextInput.onblur = function () {
if (ScratchJr.isEditable()) { if (ScratchJr.isEditable()) {
(document.forms.projectname.myproject).focus(); (document.forms.projectname.myproject).focus();
} }
}; };
UI.info.ontouchend = null; info.ontouchend = null;
ScratchJr.onBackButtonCallback.push(function () { ScratchJr.onBackButtonCallback.push(function () {
var e2 = document.createEvent('TouchEvent'); var e2 = document.createEvent('TouchEvent');
@ -383,9 +400,9 @@ UI.showInfoBox = function (e) {
//(document.forms["projectname"]["myproject"]).focus(); //(document.forms["projectname"]["myproject"]).focus();
}, 500); }, 500);
} }
}; }
UI.formatTime = function (unixtime) { static formatTime (unixtime) {
var date = new Date(unixtime); var date = new Date(unixtime);
var year = date.getFullYear(); var year = date.getFullYear();
var month = date.getMonth() + 1; var month = date.getMonth() + 1;
@ -394,17 +411,17 @@ UI.formatTime = function (unixtime) {
var min = date.getMinutes(); var min = date.getMinutes();
var sec = date.getSeconds(); var sec = date.getSeconds();
return year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec; return year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec;
}; }
UI.hideInfoBox = function (e) { static hideInfoBox (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
ScratchJr.onBackButtonCallback.pop(); ScratchJr.onBackButtonCallback.pop();
// Prevent button thrashing // Prevent button thrashing
UI.okclicky.ontouchend = null; okclicky.ontouchend = null;
setTimeout(function () { setTimeout(function () {
UI.info.ontouchend = UI.showInfoBox; info.ontouchend = UI.showInfoBox;
}, 500); }, 500);
if (ScratchJr.isEditable()) { if (ScratchJr.isEditable()) {
@ -414,13 +431,13 @@ UI.hideInfoBox = function (e) {
ScratchAudio.sndFX('exittap.wav'); ScratchAudio.sndFX('exittap.wav');
gn('infobox').className = 'infobox fade'; gn('infobox').className = 'infobox fade';
} }
}; }
////////////////////////////////////// //////////////////////////////////////
// Library // Library
///////////////////////////////////// /////////////////////////////////////
UI.layoutLibrary = function (sl) { static layoutLibrary (sl) {
var sprites = newHTML('div', 'thumbpanel', sl); var sprites = newHTML('div', 'thumbpanel', sl);
sprites.setAttribute('id', 'library'); sprites.setAttribute('id', 'library');
//scrolling area //scrolling area
@ -440,9 +457,9 @@ UI.layoutLibrary = function (sl) {
var ns = newHTML('div', 'addsprite', sprites); var ns = newHTML('div', 'addsprite', sprites);
ns.ontouchstart = UI.addSprite; ns.ontouchstart = UI.addSprite;
} }
}; }
UI.mascotData = function (page) { static mascotData (page) {
var sprAttr = { var sprAttr = {
flip: false, flip: false,
angle: 0, angle: 0,
@ -469,13 +486,13 @@ UI.mascotData = function (page) {
sprAttr.id = getIdFor(catkey); sprAttr.id = getIdFor(catkey);
sprAttr.name = catkey; sprAttr.name = catkey;
return sprAttr; return sprAttr;
}; }
////////////////////////////////////// //////////////////////////////////////
// Scrolling // Scrolling
////////////////////////////////////// //////////////////////////////////////
UI.needsScroll = function () { static needsScroll () {
var sc = gn('spritecc'); var sc = gn('spritecc');
var p = sc.parentNode; var p = sc.parentNode;
if (((sc.scrollHeight / p.offsetHeight) == 1) || (gn('spritecc').childElementCount == 0)) { if (((sc.scrollHeight / p.offsetHeight) == 1) || (gn('spritecc').childElementCount == 0)) {
@ -484,9 +501,9 @@ UI.needsScroll = function () {
gn('scrollbar').setAttribute('class', 'scrollbar on'); gn('scrollbar').setAttribute('class', 'scrollbar on');
UI.updateSpriteScroll(); UI.updateSpriteScroll();
} }
}; }
UI.updateSpriteScroll = function () { static updateSpriteScroll () {
var sc = gn('spritecc'); var sc = gn('spritecc');
var dy = sc.offsetTop; var dy = sc.offsetTop;
var p = sc.parentNode; var p = sc.parentNode;
@ -495,9 +512,9 @@ UI.updateSpriteScroll = function () {
var thumb = gn('sbthumb'); var thumb = gn('sbthumb');
thumb.style.height = size + 'px'; thumb.style.height = size + 'px';
thumb.style.top = top + 'px'; thumb.style.top = top + 'px';
}; }
UI.scrollContents = function (dy) { static scrollContents (dy) {
var sc = gn('spritecc'); var sc = gn('spritecc');
var valy = sc.offsetTop - dy; var valy = sc.offsetTop - dy;
if (valy > 0) { if (valy > 0) {
@ -511,9 +528,9 @@ UI.scrollContents = function (dy) {
} }
}; };
CSSTransition(sc, transition); CSSTransition(sc, transition);
}; }
UI.spriteInView = function (spr) { static spriteInView (spr) {
var sc = gn('spritecc'); var sc = gn('spritecc');
var achild = spr.thumbnail; var achild = spr.thumbnail;
if (!achild) { if (!achild) {
@ -533,20 +550,20 @@ UI.spriteInView = function (spr) {
} }
sc.style.top = dy + 'px'; sc.style.top = dy + 'px';
UI.needsScroll(); UI.needsScroll();
}; }
UI.resetSpriteLibrary = function () { static resetSpriteLibrary () {
if (!ScratchJr.getSprite()) { if (!ScratchJr.getSprite()) {
return; return;
} }
UI.spriteInView(ScratchJr.getSprite()); UI.spriteInView(ScratchJr.getSprite());
}; }
/////////////////////////////////// ///////////////////////////////////
// Sprite Thumbs Events // Sprite Thumbs Events
////////////////////////////////// //////////////////////////////////
UI.spriteThumbsActions = function (e) { static spriteThumbsActions (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -581,9 +598,9 @@ UI.spriteThumbsActions = function (e) {
} else { } else {
UI.startSpriteScroll(e, tb); UI.startSpriteScroll(e, tb);
} }
}; }
UI.startSpriteScroll = function (e, tb) { static startSpriteScroll (e, tb) {
if (ScratchJr.shaking) { if (ScratchJr.shaking) {
ScratchJr.clearSelection(); ScratchJr.clearSelection();
} }
@ -597,26 +614,26 @@ UI.startSpriteScroll = function (e, tb) {
Events.startDrag(e, tb, UI.prepareToScroll, UI.stopScroll, UI.spriteScolling, UI.spriteClicked, Events.startDrag(e, tb, UI.prepareToScroll, UI.stopScroll, UI.spriteScolling, UI.spriteClicked,
ScratchJr.isEditable() ? Thumbs.startCharShaking : undefined); ScratchJr.isEditable() ? Thumbs.startCharShaking : undefined);
} }
}; }
UI.ignoreEvent = function (e) { static ignoreEvent (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
}; }
UI.prepareToScroll = function (e) { static prepareToScroll (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
UI.spriteScolling(e, Events.dragthumbnail); UI.spriteScolling(e, Events.dragthumbnail);
}; }
UI.stopScroll = function (e) { static stopScroll (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
UI.spriteScolling(e, Events.dragthumbnail); UI.spriteScolling(e, Events.dragthumbnail);
}; }
UI.spriteScolling = function (e) { static spriteScolling (e) {
var pt = Events.getTargetPoint(e); var pt = Events.getTargetPoint(e);
var deltay = Events.dragmousey - pt.y; var deltay = Events.dragmousey - pt.y;
Events.dragmousey = pt.y; Events.dragmousey = pt.y;
@ -632,9 +649,9 @@ UI.spriteScolling = function (e) {
} }
sc.style.top = dy + 'px'; sc.style.top = dy + 'px';
UI.updateSpriteScroll(); UI.updateSpriteScroll();
}; }
UI.spriteClicked = function (e, el) { static spriteClicked (e, el) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var t; var t;
@ -653,9 +670,9 @@ UI.spriteClicked = function (e, el) {
el.setAttribute('class', 'spritethumb on'); el.setAttribute('class', 'spritethumb on');
} }
Thumbs.clickOnSprite(e, el); Thumbs.clickOnSprite(e, el);
}; }
UI.putInPaintEditor = function (e) { static putInPaintEditor (e) {
ScratchJr.unfocus(e); ScratchJr.unfocus(e);
var s = ScratchJr.getSprite(); var s = ScratchJr.getSprite();
if (!s) { if (!s) {
@ -663,13 +680,13 @@ UI.putInPaintEditor = function (e) {
} }
ScratchJr.stopStrips(); ScratchJr.stopStrips();
Paint.open(false, s.md5, s.id, s.name, s.defaultScale, Math.round(s.w), Math.round(s.h)); Paint.open(false, s.md5, s.id, s.name, s.defaultScale, Math.round(s.w), Math.round(s.h));
}; }
/////////////////////////////// ///////////////////////////////
// Setup Stage Variables // Setup Stage Variables
////////////////////////////// //////////////////////////////
UI.stageArea = function (inner) { static stageArea (inner) {
var outerDiv = newHTML('div', 'centerpanel', inner); var outerDiv = newHTML('div', 'centerpanel', inner);
var div = newHTML('div', 'stageframe', outerDiv); var div = newHTML('div', 'stageframe', outerDiv);
div.setAttribute('id', 'stageframe'); div.setAttribute('id', 'stageframe');
@ -684,9 +701,9 @@ UI.stageArea = function (inner) {
UI.creatTopBarClicky(div, 'resetall', 'resetall', UI.resetAllSprites); UI.creatTopBarClicky(div, 'resetall', 'resetall', UI.resetAllSprites);
UI.creatTopBarClicky(div, 'full', 'fullscreen', ScratchJr.fullScreen); UI.creatTopBarClicky(div, 'full', 'fullscreen', ScratchJr.fullScreen);
UI.toggleGrid(true); UI.toggleGrid(true);
}; }
UI.resetAllSprites = function (e) { static resetAllSprites (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (ScratchJr.onHold) { if (ScratchJr.onHold) {
@ -697,34 +714,34 @@ UI.resetAllSprites = function (e) {
ScratchJr.stopStripsFromTop(e); ScratchJr.stopStripsFromTop(e);
} }
ScratchJr.resetSprites(); ScratchJr.resetSprites();
}; }
UI.toggleRun = function (e) { static toggleRun (e) {
var isOff = ScratchJr.runtime.inactive(); var isOff = ScratchJr.runtime.inactive();
if (isOff) { if (isOff) {
ScratchJr.runStrips(e); ScratchJr.runStrips(e);
} else { } else {
ScratchJr.stopStripsFromTop(e); ScratchJr.stopStripsFromTop(e);
} }
}; }
UI.switchGrid = function () { static switchGrid () {
ScratchAudio.sndFX('tap.wav'); ScratchAudio.sndFX('tap.wav');
UI.toggleGrid(!Grid.hidden); UI.toggleGrid(!Grid.hidden);
}; }
UI.toggleGrid = function (b) { static toggleGrid (b) {
Grid.hide(b); Grid.hide(b);
gn('grid').className = Grid.hidden ? 'gridToggle off' : 'gridToggle on'; gn('grid').className = Grid.hidden ? 'gridToggle off' : 'gridToggle on';
}; }
UI.creatTopBarClicky = function (p, str, mstyle, fcn) { static creatTopBarClicky (p, str, mstyle, fcn) {
var toggle = newHTML('div', mstyle, p); var toggle = newHTML('div', mstyle, p);
toggle.ontouchstart = fcn; toggle.ontouchstart = fcn;
toggle.setAttribute('id', str); toggle.setAttribute('id', str);
}; }
UI.fullscreenControls = function () { static fullscreenControls () {
UI.nextpage = newHTML('div', 'nextpage off', frame); UI.nextpage = newHTML('div', 'nextpage off', frame);
UI.prevpage = newHTML('div', 'nextpage off', frame); UI.prevpage = newHTML('div', 'nextpage off', frame);
if (isTablet) { if (isTablet) {
@ -737,9 +754,9 @@ UI.fullscreenControls = function () {
} else { } else {
UI.prevpage.onmousedown = UI.prevPage; UI.prevpage.onmousedown = UI.prevPage;
} }
}; }
UI.updatePageControls = function () { static updatePageControls () {
var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage); var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage);
if (n == 0) { if (n == 0) {
UI.prevpage.setAttribute('class', 'prevpage off'); UI.prevpage.setAttribute('class', 'prevpage off');
@ -751,9 +768,9 @@ UI.updatePageControls = function () {
} else { } else {
UI.nextpage.setAttribute('class', 'nextpage on'); UI.nextpage.setAttribute('class', 'nextpage on');
} }
}; }
UI.nextPage = function (e) { static nextPage (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage); var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage);
@ -762,9 +779,9 @@ UI.nextPage = function (e) {
return; return;
} }
ScratchJr.stage.setPage(ScratchJr.stage.pages[n], false); ScratchJr.stage.setPage(ScratchJr.stage.pages[n], false);
}; }
UI.prevPage = function (e) { static prevPage (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage); var n = ScratchJr.stage.pages.indexOf(ScratchJr.stage.currentPage);
@ -772,9 +789,9 @@ UI.prevPage = function (e) {
return; return;
} }
ScratchJr.stage.setPage(ScratchJr.stage.pages[n - 1], false); ScratchJr.stage.setPage(ScratchJr.stage.pages[n - 1], false);
}; }
UI.enterFullScreen = function () { static enterFullScreen () {
var w = Math.min(getDocumentWidth(), frame.offsetWidth); var w = Math.min(getDocumentWidth(), frame.offsetWidth);
var h = Math.max(getDocumentHeight(), frame.offsetHeight); var h = Math.max(getDocumentHeight(), frame.offsetHeight);
frame.appendChild(gn('stage')); frame.appendChild(gn('stage'));
@ -794,9 +811,9 @@ UI.enterFullScreen = function () {
document.body.parentNode.style.background = 'black'; document.body.parentNode.style.background = 'black';
gn('stage').setAttribute('class', 'stage fullscreen'); gn('stage').setAttribute('class', 'stage fullscreen');
UI.nextpage.setAttribute('class', 'nextpage on'); UI.nextpage.setAttribute('class', 'nextpage on');
}; }
UI.quitFullScreen = function () { static quitFullScreen () {
var div = gn('stageframe'); var div = gn('stageframe');
div.appendChild(gn('stage')); div.appendChild(gn('stage'));
ScratchJr.stage.setStageScaleAndPosition(scaleMultiplier, 46, 74); ScratchJr.stage.setStageScaleAndPosition(scaleMultiplier, 46, 74);
@ -813,25 +830,25 @@ UI.quitFullScreen = function () {
ScratchJr.stage.setViewPage(ScratchJr.stage.currentPage); ScratchJr.stage.setViewPage(ScratchJr.stage.currentPage);
Thumbs.updateSprites(); Thumbs.updateSprites();
Thumbs.updatePages(); Thumbs.updatePages();
}; }
////////////////////////////////////// //////////////////////////////////////
// Right panel // Right panel
///////////////////////////////////// /////////////////////////////////////
UI.rightPanel = function (div) { static rightPanel (div) {
var rp = newHTML('div', 'rightpanel', div); var rp = newHTML('div', 'rightpanel', div);
var tb = newHTML('div', 'pages', rp); var tb = newHTML('div', 'pages', rp);
tb.setAttribute('id', 'pages'); tb.setAttribute('id', 'pages');
var ndiv = newHTML('div', 'pagescc', tb); var ndiv = newHTML('div', 'pagescc', tb);
ndiv.setAttribute('id', 'pagecc'); ndiv.setAttribute('id', 'pagecc');
}; }
////////////////////////////////////// //////////////////////////////////////
// Tools // Tools
///////////////////////////////////// /////////////////////////////////////
UI.layoutToolbar = function (div) { static layoutToolbar (div) {
var h = 56; var h = 56;
var w = 66 * 2; var w = 66 * 2;
var tb = newDiv(div, 220, 0, w, h, { var tb = newDiv(div, 220, 0, w, h, {
@ -842,9 +859,9 @@ UI.layoutToolbar = function (div) {
addt.ontouchstart = UI.addText; addt.ontouchstart = UI.addText;
var changebkg = newHTML('div', 'changeBkg', tb); var changebkg = newHTML('div', 'changeBkg', tb);
changebkg.ontouchstart = UI.addBackground; changebkg.ontouchstart = UI.addBackground;
}; }
UI.addSprite = function (e) { static addSprite (e) {
if (ScratchJr.onHold) { if (ScratchJr.onHold) {
return; return;
} }
@ -861,9 +878,9 @@ UI.addSprite = function (e) {
Events.mouseUp(e); Events.mouseUp(e);
} }
Library.open('costumes'); Library.open('costumes');
}; }
UI.addBackground = function (e) { static addBackground (e) {
if (ScratchJr.onHold) { if (ScratchJr.onHold) {
return; return;
} }
@ -875,31 +892,31 @@ UI.addBackground = function (e) {
Events.mouseUp(e); Events.mouseUp(e);
} }
Library.open('backgrounds'); Library.open('backgrounds');
}; }
UI.addText = function (e) { static addText (e) {
if (ScratchJr.onHold) { if (ScratchJr.onHold) {
return; return;
} }
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (UI.isAndroid) { if (isAndroid) {
if (gn('textbox').style.visibility === 'visible') { if (gn('textbox').style.visibility === 'visible') {
return; return;
} }
} }
ScratchJr.unfocus(e); ScratchJr.unfocus(e);
ScratchJr.stage.currentPage.createText(); ScratchJr.stage.currentPage.createText();
}; }
////////////////////////////////// //////////////////////////////////
// Key Handling in TextBox // Key Handling in TextBox
////////////////////////////////// //////////////////////////////////
UI.createFormForText = function (p) { static createFormForText (p) {
var tf = newHTML('div', 'pagetext off', p); var tf = newHTML('div', 'pagetext off', p);
tf.setAttribute('id', 'textbox'); tf.setAttribute('id', 'textbox');
if (UI.isAndroid) { if (isAndroid) {
tf.onmousedown = function (e) { tf.onmousedown = function (e) {
e.preventDefault(); e.preventDefault();
}; };
@ -927,9 +944,9 @@ UI.createFormForText = function (p) {
col.ontouchstart = UI.topLevelColor; col.ontouchstart = UI.topLevelColor;
UI.createColorMenu(tf); UI.createColorMenu(tf);
UI.createTextSizeMenu(tf); UI.createTextSizeMenu(tf);
}; }
UI.createColorMenu = function (div) { static createColorMenu (div) {
var swatchlist = BlockSpecs.fontcolors; var swatchlist = BlockSpecs.fontcolors;
var spal = newHTML('div', 'textuicolormenu off', div); var spal = newHTML('div', 'textuicolormenu off', div);
spal.setAttribute('id', 'textcolormenu'); spal.setAttribute('id', 'textcolormenu');
@ -946,9 +963,9 @@ UI.createColorMenu = function (div) {
colour.ontouchstart = UI.setTextColor; colour.ontouchstart = UI.setTextColor;
} }
UI.setMenuTextColor(gn('textcolormenu').childNodes[9]); UI.setMenuTextColor(gn('textcolormenu').childNodes[9]);
}; }
UI.createTextSizeMenu = function (div) { static createTextSizeMenu (div) {
var sizes = BlockSpecs.fontsizes; var sizes = BlockSpecs.fontsizes;
var spal = newHTML('div', 'textuifont off', div); var spal = newHTML('div', 'textuifont off', div);
spal.setAttribute('id', 'textfontsizes'); spal.setAttribute('id', 'textfontsizes');
@ -960,9 +977,9 @@ UI.createTextSizeMenu = function (div) {
textuisize.ontouchstart = UI.setTextSize; textuisize.ontouchstart = UI.setTextSize;
} }
UI.setMenuTextSize(gn('textfontsizes').childNodes[5]); UI.setMenuTextSize(gn('textfontsizes').childNodes[5]);
}; }
UI.setMenuTextColor = function (t) { static setMenuTextColor (t) {
var c = t.childNodes[0].childNodes[0].style.backgroundColor; var c = t.childNodes[0].childNodes[0].style.backgroundColor;
for (var i = 0; i < gn('textcolormenu').childElementCount; i++) { for (var i = 0; i < gn('textcolormenu').childElementCount; i++) {
var mycolor = gn('textcolormenu').childNodes[i].childNodes[0].childNodes[0].style.backgroundColor; var mycolor = gn('textcolormenu').childNodes[i].childNodes[0].childNodes[0].style.backgroundColor;
@ -972,9 +989,9 @@ UI.setMenuTextColor = function (t) {
gn('textcolormenu').childNodes[i].childNodes[1].setAttribute('class', 'splasharea off'); gn('textcolormenu').childNodes[i].childNodes[1].setAttribute('class', 'splasharea off');
} }
} }
}; }
UI.setMenuTextSize = function (t) { static setMenuTextSize (t) {
var c = t.fs; var c = t.fs;
for (var i = 0; i < gn('textfontsizes').childElementCount; i++) { for (var i = 0; i < gn('textfontsizes').childElementCount; i++) {
var kid = gn('textfontsizes').childNodes[i]; var kid = gn('textfontsizes').childNodes[i];
@ -986,13 +1003,13 @@ UI.setMenuTextSize = function (t) {
gn('textfontsizes').childNodes[i].className = 'textuisize ' + ckid + ' off'; gn('textfontsizes').childNodes[i].className = 'textuisize ' + ckid + ' off';
} }
} }
}; }
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
// Text color and size // Text color and size
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
UI.topLevelColor = function (e) { static topLevelColor (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (gn('fontcolorbutton').className == 'changecolorText on') { if (gn('fontcolorbutton').className == 'changecolorText on') {
@ -1009,9 +1026,9 @@ UI.topLevelColor = function (e) {
gn('textcolormenu').className = 'textuicolormenu on'; gn('textcolormenu').className = 'textuicolormenu on';
gn('fontcolorbutton').className = 'changecolorText on'; gn('fontcolorbutton').className = 'changecolorText on';
} }
}; }
UI.setTextColor = function (e) { static setTextColor (e) {
if (e.touches && (e.touches.length > 1)) { if (e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -1043,9 +1060,9 @@ UI.setTextColor = function (e) {
ScratchJr.storyStart('UI.setTextColor'); // Record a change for sample projects in story-starter mode ScratchJr.storyStart('UI.setTextColor'); // Record a change for sample projects in story-starter mode
var ti = document.forms.activetextbox.typing; var ti = document.forms.activetextbox.typing;
ti.style.color = c; ti.style.color = c;
}; }
UI.openFontSizeMenu = function (e) { static openFontSizeMenu (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (gn('fontsizebutton').className == 'fontsizeText on') { if (gn('fontsizebutton').className == 'fontsizeText on') {
@ -1062,9 +1079,9 @@ UI.openFontSizeMenu = function (e) {
gn('textfontsizes').className = 'textuifont on'; gn('textfontsizes').className = 'textuifont on';
gn('fontsizebutton').className = 'fontsizeText on'; gn('fontsizebutton').className = 'fontsizeText on';
} }
}; }
UI.setTextSize = function (e) { static setTextSize (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var t; var t;
@ -1097,13 +1114,13 @@ UI.setTextSize = function (e) {
setProps(document.forms.activetextbox.style, { setProps(document.forms.activetextbox.style, {
height: ((t.fs + 10) * scaleMultiplier) + 'px' height: ((t.fs + 10) * scaleMultiplier) + 'px'
}); });
}; }
/////////////////////////////////////////// ///////////////////////////////////////////
// UI clear // UI clear
///////////////////////////////////////// /////////////////////////////////////////
UI.clear = function () { static clear () {
var costumes = gn('spritecc'); var costumes = gn('spritecc');
while (costumes.childElementCount > 0) { while (costumes.childElementCount > 0) {
costumes.removeChild(costumes.childNodes[0]); costumes.removeChild(costumes.childNodes[0]);
@ -1112,4 +1129,5 @@ UI.clear = function () {
while (pthumbs.childElementCount > 0) { while (pthumbs.childElementCount > 0) {
pthumbs.removeChild(pthumbs.childNodes[0]); pthumbs.removeChild(pthumbs.childNodes[0]);
} }
}; }
}

View file

@ -1,19 +1,26 @@
////////////////////////////////// //////////////////////////////////
// Undo / Redo Functions // Undo / Redo Functions
////////////////////////////////// //////////////////////////////////
var Undo = function () {};
Undo.buffer = []; import ScratchJr from '../ScratchJr';
Undo.index = 0; import Thumbs from './Thumbs';
Undo.aux = ''; import Project from './Project';
Undo.tryCounter; import Palette from './Palette';
import UI from './UI';
import ScratchAudio from '../../utils/ScratchAudio';
import {newHTML, isTablet, gn} from '../../utils/lib';
Undo.init = function () { let buffer = [];
Undo.index = Undo.buffer.length; let index = 0;
let tryCounter;
export default class Undo {
static init () {
index = buffer.length;
Undo.update(); Undo.update();
}; }
Undo.setup = function (p) { static setup (p) {
var div = newHTML('div', 'controlundo', p); var div = newHTML('div', 'controlundo', p);
div.setAttribute('id', 'undocontrols'); div.setAttribute('id', 'undocontrols');
var lib = [['undo', Undo.prevStep], ['redo', Undo.nextStep]]; var lib = [['undo', Undo.prevStep], ['redo', Undo.nextStep]];
@ -21,9 +28,9 @@ Undo.setup = function (p) {
Undo.newToggleClicky(div, 'id_', lib[i][0], lib[i][1]); Undo.newToggleClicky(div, 'id_', lib[i][0], lib[i][1]);
} }
Undo.update(); Undo.update();
}; }
Undo.newToggleClicky = function (p, prefix, key, fcn) { static newToggleClicky (p, prefix, key, fcn) {
var div = newHTML('div', key + 'button', p); var div = newHTML('div', key + 'button', p);
div.setAttribute('type', 'toggleclicky'); div.setAttribute('type', 'toggleclicky');
div.setAttribute('id', prefix + key); div.setAttribute('id', prefix + key);
@ -39,35 +46,35 @@ Undo.newToggleClicky = function (p, prefix, key, fcn) {
} }
} }
return div; return div;
}; }
Undo.record = function (obj) { static record (obj) {
//console.log ("record", Undo.index, JSON.stringify(obj)); //console.log ("record", index, JSON.stringify(obj));
if (ScratchJr.getActiveScript()) { if (ScratchJr.getActiveScript()) {
ScratchJr.getActiveScript().owner.removeCaret(); ScratchJr.getActiveScript().owner.removeCaret();
} }
if ((Undo.index + 1) <= Undo.buffer.length) { if ((index + 1) <= buffer.length) {
Undo.buffer.splice(Undo.index + 1, Undo.buffer.length); buffer.splice(index + 1, buffer.length);
} }
var data = Project.getUndo(); var data = Project.getUndo();
for (var key in obj) { for (var key in obj) {
data[key] = obj[key]; data[key] = obj[key];
} }
Undo.buffer.push(data); buffer.push(data);
Undo.index++; index++;
Undo.update(); Undo.update();
// Project change state is usually tracked by looking if a particular action would record an undo // Project change state is usually tracked by looking if a particular action would record an undo
// We need slightly more specific behavior for story starters, so storyStarted is unaffected here. // We need slightly more specific behavior for story starters, so storyStarted is unaffected here.
ScratchJr.changed = true; ScratchJr.changed = true;
}; }
////////////////////////////////// //////////////////////////////////
// Control buttons callbacks // Control buttons callbacks
// //
//////////////////////////////// ////////////////////////////////
Undo.prevStep = function (e) { static prevStep (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -75,20 +82,20 @@ Undo.prevStep = function (e) {
e.stopPropagation(); e.stopPropagation();
ScratchJr.unfocus(); ScratchJr.unfocus();
ScratchJr.time = e.timeStamp; ScratchJr.time = e.timeStamp;
while (Undo.index >= Undo.buffer.length) { while (index >= buffer.length) {
Undo.index--; index--;
} }
Undo.index--; index--;
var snd = (Undo.index < 0) ? 'boing.wav' : 'tap.wav'; var snd = (index < 0) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd); ScratchAudio.sndFX(snd);
if (Undo.index < 0) { if (index < 0) {
Undo.index = 0; index = 0;
} else { } else {
Undo.smartRecreate('prev', Undo.buffer[Undo.index + 1], Undo.buffer[Undo.index]); Undo.smartRecreate('prev', buffer[index + 1], buffer[index]);
}
} }
};
Undo.nextStep = function (e) { static nextStep (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; return;
} }
@ -96,17 +103,17 @@ Undo.nextStep = function (e) {
e.stopPropagation(); e.stopPropagation();
ScratchJr.unfocus(); ScratchJr.unfocus();
ScratchJr.time = e.timeStamp; ScratchJr.time = e.timeStamp;
Undo.index++; index++;
var snd = (Undo.index > Undo.buffer.length - 1) ? 'boing.wav' : 'tap.wav'; var snd = (index > buffer.length - 1) ? 'boing.wav' : 'tap.wav';
ScratchAudio.sndFX(snd); ScratchAudio.sndFX(snd);
if (Undo.index > Undo.buffer.length - 1) { if (index > buffer.length - 1) {
Undo.index = Undo.buffer.length - 1; index = buffer.length - 1;
} else { } else {
Undo.smartRecreate('next', Undo.buffer[Undo.index], Undo.buffer[Undo.index]); Undo.smartRecreate('next', buffer[index], buffer[index]);
}
} }
};
Undo.smartRecreate = function (cmd, elem, data) { static smartRecreate (cmd, elem, data) {
ScratchJr.stopStrips(); ScratchJr.stopStrips();
var action = elem.action; var action = elem.action;
var page = elem.where; var page = elem.where;
@ -182,13 +189,13 @@ Undo.smartRecreate = function (cmd, elem, data) {
break; break;
default: default:
Project.clear(); Project.clear();
Undo.recreate(Undo.buffer[Undo.index]); Undo.recreate(buffer[index]);
break; break;
} }
Undo.update(); Undo.update();
}; }
Undo.copyPage = function (obj, page) { static copyPage (obj, page) {
var sc = ScratchJr.getSprite() ? gn(ScratchJr.stage.currentPage.currentSpriteName + '_scripts') : undefined; var sc = ScratchJr.getSprite() ? gn(ScratchJr.stage.currentPage.currentSpriteName + '_scripts') : undefined;
if (sc) { if (sc) {
sc.owner.deactivate(); sc.owner.deactivate();
@ -209,18 +216,18 @@ Undo.copyPage = function (obj, page) {
} }
} }
} }
}; }
Undo.getPageOrder = function (data) { static getPageOrder (data) {
var pages = data.pages; var pages = data.pages;
var res = []; var res = [];
for (var i = 0; i < pages.length; i++) { for (var i = 0; i < pages.length; i++) {
res.push(gn(pages[i]).owner); res.push(gn(pages[i]).owner);
} }
return res; return res;
}; }
Undo.recreateAllScripts = function (data) { static recreateAllScripts (data) {
for (var n = 0; n < data.pages.length; n++) { for (var n = 0; n < data.pages.length; n++) {
var page = data[data.pages[n]]; var page = data[data.pages[n]];
var sprnames = page.sprites; var sprnames = page.sprites;
@ -239,9 +246,9 @@ Undo.recreateAllScripts = function (data) {
Undo.redoScripts(data, data.pages[n], sprnames[i]); Undo.redoScripts(data, data.pages[n], sprnames[i]);
} }
} }
}; }
Undo.removePage = function (data, str) { static removePage (data, str) {
if (!gn(str)) { if (!gn(str)) {
return; return;
} }
@ -259,9 +266,9 @@ Undo.removePage = function (data, str) {
Thumbs.updateSprites(); Thumbs.updateSprites();
Thumbs.updatePages(); Thumbs.updatePages();
} }
}; }
Undo.redoScripts = function (data, page, spr) { static redoScripts (data, page, spr) {
var div = gn(spr + '_scripts'); var div = gn(spr + '_scripts');
while (div.childElementCount > 0) { while (div.childElementCount > 0) {
div.removeChild(div.childNodes[0]); div.removeChild(div.childNodes[0]);
@ -271,9 +278,9 @@ Undo.redoScripts = function (data, page, spr) {
for (var j = 0; j < list.length; j++) { for (var j = 0; j < list.length; j++) {
sc.recreateStrip(list[j]); sc.recreateStrip(list[j]);
} }
}; }
Undo.copySprite = function (data, page, spr) { static copySprite (data, page, spr) {
var obj = data[page][spr]; var obj = data[page][spr];
var fcn = function (spr) { var fcn = function (spr) {
if (spr.type == 'sprite') { if (spr.type == 'sprite') {
@ -290,9 +297,9 @@ Undo.copySprite = function (data, page, spr) {
} }
}; };
Project.recreateObject(gn(page).owner, spr, obj, fcn, (data[page].lastSprite == spr)); Project.recreateObject(gn(page).owner, spr, obj, fcn, (data[page].lastSprite == spr));
}; }
Undo.setSprite = function (page, data) { static setSprite (page, data) {
Thumbs.updatePages(); Thumbs.updatePages();
if (page != ScratchJr.stage.currentPage.id) { if (page != ScratchJr.stage.currentPage.id) {
return; return;
@ -308,9 +315,9 @@ Undo.setSprite = function (page, data) {
UI.needsScroll(); UI.needsScroll();
Thumbs.updateSprites(); Thumbs.updateSprites();
} }
}; }
Undo.removeSprite = function (data, page, spr) { static removeSprite (data, page, spr) {
if (!gn(spr)) { if (!gn(spr)) {
return; return;
} }
@ -335,9 +342,9 @@ Undo.removeSprite = function (data, page, spr) {
th.parentNode.removeChild(th); th.parentNode.removeChild(th);
} }
Undo.setSprite(page, data); Undo.setSprite(page, data);
}; }
Undo.recreate = function (data) { static recreate (data) {
Project.mediaCount = 0; Project.mediaCount = 0;
ScratchJr.stage.pages = []; ScratchJr.stage.pages = [];
var pages = data.pages; var pages = data.pages;
@ -348,9 +355,9 @@ Undo.recreate = function (data) {
Project.recreatePage(pages[i], data[pages[i]]); Project.recreatePage(pages[i], data[pages[i]]);
} }
Undo.loadPage(data.currentPage); Undo.loadPage(data.currentPage);
}; }
Undo.loadPage = function (pageid) { static loadPage (pageid) {
var pages = ScratchJr.stage.getPagesID(); var pages = ScratchJr.stage.getPagesID();
if (pages.indexOf(pageid) < 0) { if (pages.indexOf(pageid) < 0) {
ScratchJr.stage.currentPage = ScratchJr.stage.pages[0]; ScratchJr.stage.currentPage = ScratchJr.stage.pages[0];
@ -359,7 +366,7 @@ Undo.loadPage = function (pageid) {
} }
ScratchJr.stage.currentPage.div.style.visibility = 'visible'; ScratchJr.stage.currentPage.div.style.visibility = 'visible';
ScratchJr.stage.currentPage.setPageSprites('visible'); ScratchJr.stage.currentPage.setPageSprites('visible');
Undo.tryCounter = 100; tryCounter = 100;
if (Project.mediaCount > 0) { if (Project.mediaCount > 0) {
setTimeout(function () { setTimeout(function () {
Undo.updateImages(); Undo.updateImages();
@ -367,11 +374,11 @@ Undo.loadPage = function (pageid) {
} else { } else {
Undo.doneLoading(); Undo.doneLoading();
} }
}; }
Undo.updateImages = function () { static updateImages () {
Undo.tryCounter--; tryCounter--;
var done = (Project.mediaCount < 1) || (Undo.tryCounter < 1); var done = (Project.mediaCount < 1) || (tryCounter < 1);
if (done) { if (done) {
Undo.doneLoading(); Undo.doneLoading();
} else { } else {
@ -379,45 +386,46 @@ Undo.updateImages = function () {
Undo.updateImages(); Undo.updateImages();
}, 20); }, 20);
} }
}; }
Undo.flashIcon = function (div, press) { static flashIcon (div, press) {
div.setAttribute('class', press); div.setAttribute('class', press);
setTimeout(function () { setTimeout(function () {
Undo.update(); Undo.update();
}, 1000); }, 1000);
}; }
Undo.doneLoading = function () { static doneLoading () {
Thumbs.updateSprites(); Thumbs.updateSprites();
Thumbs.updatePages(); Thumbs.updatePages();
}; }
Undo.update = function () { static update () {
if (gn('id_undo')) { if (gn('id_undo')) {
if (Undo.buffer.length == 1) { if (buffer.length == 1) {
Undo.tunOffButton(gn('id_undo')); Undo.tunOffButton(gn('id_undo'));
} else { } else {
if (Undo.index < 1) { if (index < 1) {
Undo.tunOffButton(gn('id_undo')); Undo.tunOffButton(gn('id_undo'));
} else { } else {
Undo.tunOnButton(gn('id_undo')); Undo.tunOnButton(gn('id_undo'));
} }
} }
if (Undo.index >= Undo.buffer.length - 1) { if (index >= buffer.length - 1) {
Undo.tunOffButton(gn('id_redo')); Undo.tunOffButton(gn('id_redo'));
} else { } else {
Undo.tunOnButton(gn('id_redo')); Undo.tunOnButton(gn('id_redo'));
} }
} }
}; }
Undo.tunOnButton = function (kid) { static tunOnButton (kid) {
var kclass = kid.getAttribute('class').split(' ')[0]; var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' enable'); kid.setAttribute('class', kclass + ' enable');
}; }
Undo.tunOffButton = function (kid) { static tunOffButton (kid) {
var kclass = kid.getAttribute('class').split(' ')[0]; var kclass = kid.getAttribute('class').split(' ')[0];
kid.setAttribute('class', kclass + ' disable'); kid.setAttribute('class', kclass + ' disable');
}; }
}

View file

@ -626,7 +626,6 @@ export default class Paint {
ti.getBoundingClientRect().bottom * window.devicePixelRatio ti.getBoundingClientRect().bottom * window.devicePixelRatio
); );
} }
Undo.aux = Project.getProject(ScratchJr.stage.currentPage.id);
setTimeout(function () { setTimeout(function () {
ti.setSelectionRange(ti.value.length, ti.value.length); ti.setSelectionRange(ti.value.length, ti.value.length);
}, 1); }, 1);