Convert remaining modules

This commit is contained in:
Tim Mickel 2016-01-21 15:32:41 -05:00
parent bf07d98ccd
commit 1c32ecf0a5
9 changed files with 4628 additions and 4507 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,12 @@
import ScratchJr from '../ScratchJr';
import BlockSpecs from './BlockSpecs';
import Menu from './Menu';
import Undo from '../ui/Undo';
import {setCanvasSize, setProps, writeText, scaleMultiplier,
newHTML, newDiv, newCanvas, getStringSize, isTablet,
newP, globalx, globaly} from '../../utils/lib';
import Localization from '../../utils/Localization';
/*
Argument types
@ -9,442 +18,448 @@ r: number for recorded sound block
p: page icons
*/
var BlockArg = function (block) {
this.daddy = block;
this.type = 'blockarg';
this.argType = block.spec[3];
switch (this.argType) {
case 'n':
this.argValue = block.spec[4];
this.div = this.addNumArg();
break;
case 't':
this.argValue = block.spec[4];
if (Localization.isSampleLocalizedKey(this.argValue) && ScratchJr.isSampleOrStarter()) {
this.argValue = Localization.localize('SAMPLE_TEXT_' + this.argValue);
export default class BlockArg {
constructor (block) {
this.daddy = block;
this.type = 'blockarg';
this.argType = block.spec[3];
switch (this.argType) {
case 'n':
this.argValue = block.spec[4];
this.div = this.addNumArg();
break;
case 't':
this.argValue = block.spec[4];
if (Localization.isSampleLocalizedKey(this.argValue) && ScratchJr.isSampleOrStarter()) {
this.argValue = Localization.localize('SAMPLE_TEXT_' + this.argValue);
}
this.div = this.addTextArg();
break;
case 'm':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = this.getIconFrom(block.spec[4], block.spec[1]);
this.div = this.addImageMenu(this.closePictureMenu);
break;
case 'd':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = BlockSpecs.speeds[this.argValue];
this.div = this.addImageMenu(this.menuCloseSpeeds);
break;
case 'p':
this.argValue = block.spec[4];
this.div = this.pageIcon(this.argValue);
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
break;
case 's':
this.argValue = block.spec[4];
this.div = newDiv(block.div, 2, 46, 60, 20, {
position: 'absolute',
zoom: (block.scale * 100) + '%'
});
var p = newP(this.div, this.argValue.split('.')[0], {
width: '60px'
});
p.setAttribute('class', 'soundname');
break;
case 'r':
this.argValue = block.spec[4];
this.div = newHTML('div', 'recordedCircle', block.div);
setProps(this.div.style, {
zoom: (block.scale * 100) + '%'
});
var num = newHTML('p', 'recordedNumber', this.div);
num.textContent = this.daddy.inpalette ? this.argValue : '?';
break;
default:
break;
}
this.div = this.addTextArg();
break;
case 'm':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = this.getIconFrom(block.spec[4], block.spec[1]);
this.div = this.addImageMenu(this.closePictureMenu);
break;
case 'd':
this.argValue = block.spec[4];
this.list = JSON.stringify(block.spec[1]);
this.numperrow = 3;
this.icon = BlockSpecs.speeds[this.argValue];
this.div = this.addImageMenu(this.menuCloseSpeeds);
break;
case 'p':
this.argValue = block.spec[4];
this.div = this.pageIcon(this.argValue);
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
break;
case 's':
this.argValue = block.spec[4];
this.div = newDiv(block.div, 2, 46, 60, 20, {
position: 'absolute',
zoom: (block.scale * 100) + '%'
});
var p = newP(this.div, this.argValue.split('.')[0], {
width: '60px'
});
p.setAttribute('class', 'soundname');
break;
case 'r':
this.argValue = block.spec[4];
this.div = newHTML('div', 'recordedCircle', block.div);
setProps(this.div.style, {
zoom: (block.scale * 100) + '%'
});
var num = newHTML('p', 'recordedNumber', this.div);
num.textContent = this.daddy.inpalette ? this.argValue : '?';
break;
default:
break;
}
};
BlockArg.prototype.update = function () {
if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue;
update () {
if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue;
}
if (this.arg && (this.argType == 'p')) {
this.arg.updateIcon();
}
}
if (this.arg && (this.argType == 'p')) {
this.arg.updateIcon();
}
};
BlockArg.prototype.getScreenPt = function () {
return {
x: globalx(this.daddy.div),
y: globaly(this.daddy.div)
};
};
BlockArg.prototype.addNumArg = function () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, false);
} else {
return this.addNumArgument(str);
}
};
BlockArg.prototype.addTextArg = function () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, true);
} else {
return this.addTextArgument(str, true);
}
};
BlockArg.prototype.addLabel = function (str, isText) {
var scale = this.daddy.scale;
var dx = isText ? 8 : 16;
var dy = 57;
if (this.daddy.blocktype == 'repeat') {
dx = Math.round(this.daddy.blockshape.width / window.devicePixelRatio / scale) - 60;
dy = Math.round(this.daddy.blockshape.height / window.devicePixelRatio / scale) - 10;
}
var img = isText ? BlockSpecs.textfieldimg : BlockSpecs.numfieldimg;
var w = isText ? 53 : 36;
var h = 17;
var field = newCanvas(this.daddy.div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (scale / window.devicePixelRatio) + ') ' +
'translate(' + (dx * window.devicePixelRatio + (w * window.devicePixelRatio / 2)) + 'px, ' +
(dy * window.devicePixelRatio + (h * window.devicePixelRatio / 2)) + 'px)',
pointerEvents: 'all'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
getScreenPt () {
return {
x: globalx(this.daddy.div),
y: globaly(this.daddy.div)
};
} else {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
}
var div = newDiv(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
margin: '0px',
padding: '0px'
});
var cnv = newCanvas(div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (w * window.devicePixelRatio / 2) + 'px, ' + (h * window.devicePixelRatio / 2) + 'px)'
});
ctx = cnv.getContext('2d');
var font = (12 * window.devicePixelRatio) + 'px ' + Settings.blockArgFont;
var lsize = getStringSize(ctx, font, str).width;
writeText(ctx, font, '#77787b', str, h * window.devicePixelRatio - 3,
Math.round((w * window.devicePixelRatio - lsize) / 2));
return div;
};
BlockArg.prototype.addNumArgument = function (str) {
var div = newHTML('div', 'numfield', this.daddy.div);
if (this.daddy.blocktype == 'repeat') {
setProps(div.style, {
left: (this.daddy.blockshape.width / window.devicePixelRatio - 62 * this.daddy.scale) + 'px',
top: (this.daddy.blockshape.height / window.devicePixelRatio - 11 * this.daddy.scale) + 'px'
});
}
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
BlockArg.prototype.addTextArgument = function (str) {
var div = newHTML('div', 'textfield', this.daddy.div);
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
BlockArg.prototype.setValue = function (val) {
if (!this.input) {
return;
}
this.argValue = val;
this.input.textContent = val;
};
BlockArg.prototype.isText = function () {
return (this.argType != 'n');
};
/////////////////////////////////
// Menu drop downs
//////////////////////////////
BlockArg.prototype.getIconFrom = function (key, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].indexOf(key) > -1) {
return list[i];
addNumArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, false);
} else {
return this.addNumArgument(str);
}
}
return list[0];
};
BlockArg.prototype.addImageMenu = function (fcn) {
this.drawChoice(this.daddy.blockicon);
this.button = this.addPressButton();
if (!this.daddy.inpalette) {
var ba = this;
if (isTablet) {
ba.button.ontouchstart = function (evt) {
ba.pressDropDown(evt, fcn);
addTextArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, true);
} else {
return this.addTextArgument(str, true);
}
}
addLabel (str, isText) {
var scale = this.daddy.scale;
var dx = isText ? 8 : 16;
var dy = 57;
if (this.daddy.blocktype == 'repeat') {
dx = Math.round(this.daddy.blockshape.width / window.devicePixelRatio / scale) - 60;
dy = Math.round(this.daddy.blockshape.height / window.devicePixelRatio / scale) - 10;
}
var img = isText ? BlockSpecs.textfieldimg : BlockSpecs.numfieldimg;
var w = isText ? 53 : 36;
var h = 17;
var field = newCanvas(this.daddy.div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (scale / window.devicePixelRatio) + ') ' +
'translate(' + (dx * window.devicePixelRatio + (w * window.devicePixelRatio / 2)) + 'px, ' +
(dy * window.devicePixelRatio + (h * window.devicePixelRatio / 2)) + 'px)',
pointerEvents: 'all'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
};
} else {
ba.button.onmousedown = function (evt) {
ba.pressDropDown(evt, fcn);
};
ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
}
var div = newDiv(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
margin: '0px',
padding: '0px'
});
var cnv = newCanvas(div, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio, {
position: 'absolute',
webkitTransform: 'translate(' + (-w * window.devicePixelRatio / 2) + 'px, ' +
(-h * window.devicePixelRatio / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (w * window.devicePixelRatio / 2) + 'px, ' + (h * window.devicePixelRatio / 2) + 'px)'
});
ctx = cnv.getContext('2d');
var font = (12 * window.devicePixelRatio) + 'px ' + Settings.blockArgFont;
var lsize = getStringSize(ctx, font, str).width;
writeText(ctx, font, '#77787b', str, h * window.devicePixelRatio - 3,
Math.round((w * window.devicePixelRatio - lsize) / 2));
return div;
}
addNumArgument (str) {
var div = newHTML('div', 'numfield', this.daddy.div);
if (this.daddy.blocktype == 'repeat') {
setProps(div.style, {
left: (this.daddy.blockshape.width / window.devicePixelRatio - 62 * this.daddy.scale) + 'px',
top: (this.daddy.blockshape.height / window.devicePixelRatio - 11 * this.daddy.scale) + 'px'
});
}
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
}
this.button.parentNode.height += this.button.height / 2;
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height);
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
}
return this.daddy.blockicon;
};
BlockArg.prototype.drawChoice = function (cnv) {
var ctx = cnv.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg');
var scale = this.daddy.scale;
if (!icon.complete) {
icon.onload = function () {
addTextArgument (str) {
var div = newHTML('div', 'textfield', this.daddy.div);
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
}
setValue (val) {
if (!this.input) {
return;
}
this.argValue = val;
this.input.textContent = val;
}
isText () {
return (this.argType != 'n');
}
/////////////////////////////////
// Menu drop downs
//////////////////////////////
getIconFrom (key, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].indexOf(key) > -1) {
return list[i];
}
}
return list[0];
}
addImageMenu (fcn) {
this.drawChoice(this.daddy.blockicon);
this.button = this.addPressButton();
if (!this.daddy.inpalette) {
var ba = this;
if (isTablet) {
ba.button.ontouchstart = function (evt) {
ba.pressDropDown(evt, fcn);
};
} else {
ba.button.onmousedown = function (evt) {
ba.pressDropDown(evt, fcn);
};
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
}
this.button.parentNode.height += this.button.height / 2;
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height);
}
return this.daddy.blockicon;
}
drawChoice (cnv) {
var ctx = cnv.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg');
var scale = this.daddy.scale;
if (!icon.complete) {
icon.onload = function () {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
}
return cnv;
}
return cnv;
};
BlockArg.prototype.addPressButton = function () {
var scale = this.daddy.scale;
var dx;
if (this.daddy.inpalette) {
dx = this.daddy.aStart ? 26 : 16;
} else {
dx = this.daddy.aStart ? 20 : 10;
}
var dy = 56;
var w = (this.daddy.inpalette) ? 36 : 48;
var h = (this.daddy.inpalette) ? 20 : 27;
var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton;
var field = newCanvas(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
pointerEvents: 'all',
webkitTransform: 'translateZ(0)'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
addPressButton () {
var scale = this.daddy.scale;
var dx;
if (this.daddy.inpalette) {
dx = this.daddy.aStart ? 26 : 16;
} else {
dx = this.daddy.aStart ? 20 : 10;
}
var dy = 56;
var w = (this.daddy.inpalette) ? 36 : 48;
var h = (this.daddy.inpalette) ? 20 : 27;
var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton;
var field = newCanvas(this.daddy.div, dx, dy, w, h, {
position: 'absolute',
zoom: (scale * 100) + '%',
pointerEvents: 'all',
webkitTransform: 'translateZ(0)'
});
var ctx = field.getContext('2d');
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0);
};
} else {
ctx.drawImage(img, 0, 0);
};
} else {
ctx.drawImage(img, 0, 0);
}
return field;
}
return field;
};
BlockArg.prototype.pressDropDown = function (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
pressDropDown (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
if (ScratchJr.onHold) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus(e);
if (!this.daddy) {
return;
}
Menu.openDropDown(this.daddy.div, fcn);
}
if (ScratchJr.onHold) {
return;
}
e.preventDefault();
e.stopPropagation();
ScratchJr.unfocus(e);
if (!this.daddy) {
return;
}
Menu.openDropDown(this.daddy.div, fcn);
};
BlockArg.prototype.closePictureMenu = function (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio, 66 * scaleMultiplier * window.devicePixelRatio);
if (!b.icon.complete) {
b.icon.onload = function () {
closePictureMenu (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio,
66 * scaleMultiplier * window.devicePixelRatio);
if (!b.icon.complete) {
b.icon.onload = function () {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio);
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.closePictureMenu');
}
Menu.openMenu = undefined;
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.closePictureMenu');
}
Menu.openMenu = undefined;
};
BlockArg.prototype.menuCloseSpeeds = function (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio, 64 * scaleMultiplier * window.devicePixelRatio);
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.style.display = 'none';
b.owner.blockicon.offsetHeight;
b.owner.blockicon.style.display = 'inherit';
if (!b.icon.complete) {
b.icon.onload = function () {
menuCloseSpeeds (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio,
64 * scaleMultiplier * window.devicePixelRatio);
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.style.display = 'none';
b.owner.blockicon.offsetHeight;
b.owner.blockicon.style.display = 'inherit';
if (!b.icon.complete) {
b.icon.onload = function () {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
};
} else {
var w = b.icon.width;
var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.menuCloseSpeeds');
}
Menu.openMenu = undefined;
}
if (Menu.openMenu) {
Menu.openMenu.parentNode.removeChild(Menu.openMenu);
}
if (b.owner.arg.argValue != value) {
var spr = b.parentNode.owner.spr;
var action = {
action: 'scripts',
where: spr.div.parentNode.owner.id,
who: spr.id
};
Undo.record(action);
ScratchJr.storyStart('BlockArg.prototype.menuCloseSpeeds');
}
Menu.openMenu = undefined;
};
//////////////////////////
// Page Icon
//////////////////////////
//////////////////////////
// Page Icon
//////////////////////////
BlockArg.prototype.pageIcon = function (num) {
var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas');
setCanvasSize(icon, 86 * dpr, 66 * dpr);
if (!page) {
pageIcon (num) {
var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas');
setCanvasSize(icon, 86 * dpr, 66 * dpr);
if (!page) {
return icon;
}
var canvas = document.createElement('canvas');
setCanvasSize(canvas, 52 * dpr, 42 * dpr);
var mainctx = canvas.getContext('2d');
mainctx.fillStyle = '#AE1F24';
mainctx.fillRect(0, 0, canvas.width, canvas.height);
mainctx.fillStyle = '#28A5DA';
mainctx.fillRect(1 * dpr, 1 * dpr, 50 * dpr, 40 * dpr);
var c = document.createElement('canvas');
var w = (52 - 6) * dpr;
var h = (42 - 6) * dpr;
setCanvasSize(c, w, h);
var ctx = c.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, c.width, c.height);
if (page.bkg.childElementCount > 0) {
var img = page.bkg.childNodes[0];
var imgw = img.naturalWidth ? img.naturalWidth : img.width;
var imgh = img.naturalHeight ? img.naturalHeight : img.height;
ctx.drawImage(img, 0, 0, imgw, imgh, 0, 0, w, h);
}
var scale = w / 480;
for (var i = 0; i < page.div.childElementCount; i++) {
var spr = page.div.childNodes[i].owner;
if (!spr) {
continue;
}
page.stampSpriteAt(ctx, spr, scale);
}
mainctx.drawImage(c, 3 * dpr, 3 * dpr);
var ictx = icon.getContext('2d');
ictx.fillStyle = '#AE1F24';
ictx.beginPath();
ictx.arc(63 * dpr, 19 * dpr, 10 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.fill();
ictx.drawImage(canvas, 14 * dpr, 16 * dpr);
ictx.beginPath();
ictx.fillStyle = '#28A5DA';
ictx.strokeStyle = '#355E7C';
ictx.arc(63 * dpr, 19 * dpr, 8 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.stroke();
ictx.fill();
writeText(ictx, 'bold ' + (12 * dpr) + 'px ' + Settings.blockArgFont, 'white', page.num, 26 * dpr, 58 * dpr);
return icon;
}
var canvas = document.createElement('canvas');
setCanvasSize(canvas, 52 * dpr, 42 * dpr);
var mainctx = canvas.getContext('2d');
mainctx.fillStyle = '#AE1F24';
mainctx.fillRect(0, 0, canvas.width, canvas.height);
mainctx.fillStyle = '#28A5DA';
mainctx.fillRect(1 * dpr, 1 * dpr, 50 * dpr, 40 * dpr);
var c = document.createElement('canvas');
var w = (52 - 6) * dpr;
var h = (42 - 6) * dpr;
setCanvasSize(c, w, h);
var ctx = c.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, c.width, c.height);
if (page.bkg.childElementCount > 0) {
var img = page.bkg.childNodes[0];
var imgw = img.naturalWidth ? img.naturalWidth : img.width;
var imgh = img.naturalHeight ? img.naturalHeight : img.height;
ctx.drawImage(img, 0, 0, imgw, imgh, 0, 0, w, h);
}
var scale = w / 480;
for (var i = 0; i < page.div.childElementCount; i++) {
var spr = page.div.childNodes[i].owner;
if (!spr) {
continue;
}
page.stampSpriteAt(ctx, spr, scale);
}
mainctx.drawImage(c, 3 * dpr, 3 * dpr);
var ictx = icon.getContext('2d');
ictx.fillStyle = '#AE1F24';
ictx.beginPath();
ictx.arc(63 * dpr, 19 * dpr, 10 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.fill();
ictx.drawImage(canvas, 14 * dpr, 16 * dpr);
ictx.beginPath();
ictx.fillStyle = '#28A5DA';
ictx.strokeStyle = '#355E7C';
ictx.arc(63 * dpr, 19 * dpr, 8 * dpr, 0 * dpr, Math.PI * 2, true);
ictx.closePath();
ictx.stroke();
ictx.fill();
writeText(ictx, 'bold ' + (12 * dpr) + 'px ' + Settings.blockArgFont, 'white', page.num, 26 * dpr, 58 * dpr);
return icon;
};
BlockArg.prototype.updateIcon = function () {
var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1];
page.num = num;
this.div = this.pageIcon(num);
var block = this.daddy;
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
};
updateIcon () {
var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1];
page.num = num;
this.div = this.pageIcon(num);
var block = this.daddy;
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,179 +1,187 @@
var Runtime = function () {
this.threadsRunning = [];
this.thread = undefined;
this.intervalId = undefined;
this.yield = false;
};
import ScratchJr from '../ScratchJr';
import Project from '../../ui/Project';
import Prims from './Prims';
import Thread from './Thread';
Runtime.prototype.beginTimer = function () {
if (this.intervalId != null) {
window.clearInterval(this.intervalId);
export default class Runtime {
constructor () {
this.threadsRunning = [];
this.thread = undefined;
this.intervalId = undefined;
this.yield = false;
}
var rt = this;
this.intervalId = window.setInterval(function () {
rt.tickTask();
}, 32);
Project.saving = false;
// Prims.time = (new Date() - 0);
this.threadsRunning = [];
};
Runtime.prototype.tickTask = function () {
ScratchJr.updateRunStopButtons();
if (this.threadsRunning.length < 1) {
return;
}
var activeThreads = [];
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].isRunning) {
activeThreads.push(this.threadsRunning[i]);
beginTimer () {
if (this.intervalId != null) {
window.clearInterval(this.intervalId);
}
var rt = this;
this.intervalId = window.setInterval(function () {
rt.tickTask();
}, 32);
Project.saving = false;
// Prims.time = (new Date() - 0);
this.threadsRunning = [];
}
this.threadsRunning = activeThreads;
for (var j = 0; j < this.threadsRunning.length; j++) {
this.step(j);
}
};
Runtime.prototype.inactive = function () {
if (this.threadsRunning.length < 1) {
return true;
}
var inactive = true;
for (var i = 0; i < this.threadsRunning.length; i++) {
var t = this.threadsRunning[i];
if (!t) {
continue;
}
if (t.isRunning && (t.firstBlock.blocktype != 'ontouch')) {
inactive = false;
}
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null) && (t.thisblock.blocktype != 'ontouch')) {
inactive = false;
}
}
return inactive;
};
Runtime.prototype.step = function (n) {
this.yield = false;
this.thread = this.threadsRunning[n];
while (true) { // eslint-disable-line no-constant-condition
if (!this.thread.isRunning) {
tickTask () {
ScratchJr.updateRunStopButtons();
if (this.threadsRunning.length < 1) {
return;
}
if (this.thread.waitTimer > 0) {
this.thread.waitTimer += -1;
return;
}
// if (this.thread.spr.parentNode.id == "frame") return; // object is being dragged
if (this.yield) {
return;
}
if (this.thread.thisblock == null) {
this.endCase();
this.yield = true;
} else {
this.runPrim();
}
}
};
Runtime.prototype.addRunScript = function (spr, b) {
this.restartThread(spr, b);
};
Runtime.prototype.stopThreads = function () {
for (var i in this.threadsRunning) {
this.threadsRunning[i].stop();
}
this.threadsRunning = [];
};
Runtime.prototype.stopThreadBlock = function (b) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].firstBlock == b) {
this.threadsRunning[i].stop();
}
}
};
Runtime.prototype.stopThreadSprite = function (spr) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
this.threadsRunning[i].stop();
}
}
};
Runtime.prototype.removeRunScript = function (spr) {
var res = [];
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
var activeThreads = [];
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].isRunning) {
if (this.threadsRunning[i].thisblock != null) {
this.threadsRunning[i].endPrim();
activeThreads.push(this.threadsRunning[i]);
}
}
this.threadsRunning = activeThreads;
for (var j = 0; j < this.threadsRunning.length; j++) {
this.step(j);
}
}
inactive () {
if (this.threadsRunning.length < 1) {
return true;
}
var inactive = true;
for (var i = 0; i < this.threadsRunning.length; i++) {
var t = this.threadsRunning[i];
if (!t) {
continue;
}
if (t.isRunning && (t.firstBlock.blocktype != 'ontouch')) {
inactive = false;
}
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null)
&& (t.thisblock.blocktype != 'ontouch')) {
inactive = false;
}
}
return inactive;
}
step (n) {
this.yield = false;
this.thread = this.threadsRunning[n];
while (true) { // eslint-disable-line no-constant-condition
if (!this.thread.isRunning) {
return;
}
if (this.thread.waitTimer > 0) {
this.thread.waitTimer += -1;
return;
}
// if (this.thread.spr.parentNode.id == "frame") return; // object is being dragged
if (this.yield) {
return;
}
if (this.thread.thisblock == null) {
this.endCase();
this.yield = true;
} else {
this.runPrim();
}
}
}
addRunScript (spr, b) {
this.restartThread(spr, b);
}
stopThreads () {
for (var i in this.threadsRunning) {
this.threadsRunning[i].stop();
}
this.threadsRunning = [];
}
stopThreadBlock (b) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].firstBlock == b) {
this.threadsRunning[i].stop();
}
}
}
stopThreadSprite (spr) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
this.threadsRunning[i].stop();
}
}
}
removeRunScript (spr) {
var res = [];
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
if (this.threadsRunning[i].isRunning) {
if (this.threadsRunning[i].thisblock != null) {
this.threadsRunning[i].endPrim();
}
res.push(this.threadsRunning[i].duplicate());
}
res.push(this.threadsRunning[i].duplicate());
}
this.threadsRunning[i].isRunning = false;
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
}
}
return res;
};
Runtime.prototype.runPrim = function () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
this.thread.oldblock = null;
var token = Prims.table[this.thread.thisblock.blocktype];
if (token == null) {
token = Prims.table.missing;
} else {
var noh = ['repeat', 'gotopage'];
if (noh.indexOf(this.thread.thisblock.blocktype) < 0) {
this.thread.thisblock.highlight();
this.thread.oldblock = this.thread.thisblock;
}
Prims.time = (new Date() - 0);
token(this.thread);
}
};
Runtime.prototype.endCase = function () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
if (this.thread.stack.length == 0) {
Prims.Done(this.thread);
} else {
var thing = (this.thread.stack).pop();
this.thread.thisblock = thing;
this.runPrim();
}
};
Runtime.prototype.restartThread = function (spr, b, active) {
var newThread = new Thread(spr, b);
var wasRunning = false;
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].firstBlock == b) {
wasRunning = true;
if (b.blocktype != 'ontouch') { // on touch demons are special - they are not interruptable
this.threadsRunning[i].isRunning = false;
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
this.threadsRunning[i].stopping(active);
newThread = this.threadsRunning[i];
}
}
return res;
}
if (!wasRunning) {
this.threadsRunning.push(newThread);
runPrim () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
this.thread.oldblock = null;
var token = Prims.table[this.thread.thisblock.blocktype];
if (token == null) {
token = Prims.table.missing;
} else {
var noh = ['repeat', 'gotopage'];
if (noh.indexOf(this.thread.thisblock.blocktype) < 0) {
this.thread.thisblock.highlight();
this.thread.oldblock = this.thread.thisblock;
}
Prims.time = (new Date() - 0);
token(this.thread);
}
}
return newThread;
};
endCase () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
if (this.thread.stack.length == 0) {
Prims.Done(this.thread);
} else {
var thing = (this.thread.stack).pop();
this.thread.thisblock = thing;
this.runPrim();
}
}
restartThread (spr, b, active) {
var newThread = new Thread(spr, b);
var wasRunning = false;
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].firstBlock == b) {
wasRunning = true;
if (b.blocktype != 'ontouch') { // on touch demons are special - they are not interruptable
if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight();
}
this.threadsRunning[i].stopping(active);
newThread = this.threadsRunning[i];
}
}
}
if (!wasRunning) {
this.threadsRunning.push(newThread);
}
return newThread;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,159 +1,165 @@
var Thread = function (s, block) {
this.firstBlock = block.findFirst();
this.thisblock = block;
this.oldblock = null;
this.spr = s;
this.audio = undefined;
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.distance = -1;
this.called = [];
this.vector = {
x: 0,
y: 0
};
this.isRunning = true;
this.time = 0; // for debugging purposes
return this;
};
import Prims from './Prims';
import Grid from '../ui/Grid';
import Vector from '../../geom/Vector';
Thread.prototype.clear = function () {
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.vector = {
x: 0,
y: 0
};
this.distance = -1;
this.called = [];
this.thisblock = this.firstBlock;
};
Thread.prototype.duplicate = function () {
var thread = new Thread(this.spr, this.firstBlock);
thread.count = -1;
thread.firstBlock = this.firstBlock;
thread.thisblock = this.thisblock;
thread.oldblock = null;
thread.spr = this.spr;
thread.stack = this.stack;
thread.firstTime = this.firstTime;
thread.vector = {
x: 0,
y: 0
};
thread.waitTimer = 0;
thread.distance = -1;
thread.called = this.called;
thread.isRunning = this.isRunning;
return thread;
};
Thread.prototype.deselect = function (b) {
while (b != null) {
b.unhighlight();
if (b.inside) {
b.repeatCounter = -1;
this.deselect(b.inside);
}
b = b.next;
export default class Thread {
constructor (s, block) {
this.firstBlock = block.findFirst();
this.thisblock = block;
this.oldblock = null;
this.spr = s;
this.audio = undefined;
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.distance = -1;
this.called = [];
this.vector = {
x: 0,
y: 0
};
this.isRunning = true;
this.time = 0; // for debugging purposes
return this;
}
};
Thread.prototype.stop = function (b) {
this.stopping(b);
this.isRunning = false;
};
Thread.prototype.stopping = function (b) {
this.endPrim(b);
this.deselect(this.firstBlock);
this.clear();
this.spr.closeBalloon();
};
Thread.prototype.endPrim = function (stopMine) {
if (!this.thisblock) {
return;
clear () {
this.stack = [];
this.firstTime = true;
this.count = -1;
this.waitTimer = 0;
this.vector = {
x: 0,
y: 0
};
this.distance = -1;
this.called = [];
this.thisblock = this.firstBlock;
}
var b = this.thisblock;
var s = this.spr;
switch (b.blocktype) {
case 'down':
case 'back':
case 'forward':
case 'up':
if ((this.distance > -1) && !stopMine) {
var vector = Vector.scale(this.vector, this.distance % 24);
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y);
}
break;
case 'hop':
var count = this.count;
var n = Number(b.getArgValue());
count--;
if (count > 0) {
var delta = 0;
for (var i = count; i > -1; i--) {
delta += Prims.hopList[count];
}
this.vector = {
x: 0,
y: delta
};
var dy = s.ycoor - this.vector.y / 5 * n;
if (dy < 0) {
dy = 0;
}
if (dy >= (360 - Grid.size)) {
dy = (360 - Grid.size);
}
s.setPos(s.xcoor + this.vector.x, dy);
}
break;
case 'playsnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'playusersnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'hide':
s.div.style.opacity = 0;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = false;
}
break;
case 'show':
s.div.style.opacity = 1;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = true;
}
break;
case 'same': s.noScaleFor();
break;
case 'grow':
case 'shrink':
if (!this.firstBlock.aStart && !stopMine) {
s.homescale = s.scale;
}
break;
case 'right':
case 'left':
var angle = s.angle;
if ((angle % 30) != 0) {
angle = (Math.floor(angle / 30) + 1) * 30;
}
s.setHeading(angle);
break;
duplicate () {
var thread = new Thread(this.spr, this.firstBlock);
thread.count = -1;
thread.firstBlock = this.firstBlock;
thread.thisblock = this.thisblock;
thread.oldblock = null;
thread.spr = this.spr;
thread.stack = this.stack;
thread.firstTime = this.firstTime;
thread.vector = {
x: 0,
y: 0
};
thread.waitTimer = 0;
thread.distance = -1;
thread.called = this.called;
thread.isRunning = this.isRunning;
return thread;
}
};
deselect (b) {
while (b != null) {
b.unhighlight();
if (b.inside) {
b.repeatCounter = -1;
this.deselect(b.inside);
}
b = b.next;
}
}
stop (b) {
this.stopping(b);
this.isRunning = false;
}
stopping (b) {
this.endPrim(b);
this.deselect(this.firstBlock);
this.clear();
this.spr.closeBalloon();
}
endPrim (stopMine) {
if (!this.thisblock) {
return;
}
var b = this.thisblock;
var s = this.spr;
switch (b.blocktype) {
case 'down':
case 'back':
case 'forward':
case 'up':
if ((this.distance > -1) && !stopMine) {
var vector = Vector.scale(this.vector, this.distance % 24);
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y);
}
break;
case 'hop':
var count = this.count;
var n = Number(b.getArgValue());
count--;
if (count > 0) {
var delta = 0;
for (var i = count; i > -1; i--) {
delta += Prims.hopList[count];
}
this.vector = {
x: 0,
y: delta
};
var dy = s.ycoor - this.vector.y / 5 * n;
if (dy < 0) {
dy = 0;
}
if (dy >= (360 - Grid.size)) {
dy = (360 - Grid.size);
}
s.setPos(s.xcoor + this.vector.x, dy);
}
break;
case 'playsnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'playusersnd':
if (this.audio) {
this.audio.stop();
this.audio = undefined;
}
break;
case 'hide':
s.div.style.opacity = 0;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = false;
}
break;
case 'show':
s.div.style.opacity = 1;
if (!this.firstBlock.aStart && !stopMine) {
s.homeshown = true;
}
break;
case 'same': s.noScaleFor();
break;
case 'grow':
case 'shrink':
if (!this.firstBlock.aStart && !stopMine) {
s.homescale = s.scale;
}
break;
case 'right':
case 'left':
var angle = s.angle;
if ((angle % 30) != 0) {
angle = (Math.floor(angle / 30) + 1) * 30;
}
s.setHeading(angle);
break;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,481 +2,486 @@
// Scrolling Pane
////////////////////////////////////////////////
var Scroll = function (div, id, w, h, cfcn, ofcn) {
this.hasHorizontal = true;
this.hasVertical = true;
this.arrowDistance = 6;
this.aleft = undefined;
this.aright = undefined;
this.aup = undefined;
this.adown = undefined;
this.contents = newDiv(div, 0, 0, w, h, {});
this.contents.setAttribute('id', id);
this.contents.owner = this;
this.addArrows(div, w, h);
this.getContent = cfcn;
this.getObjects = ofcn;
div.scroll = this; // for now;
};
import Events from '../../utils/Events';
import {newDiv, newHTML, CSSTransition3D, isTablet, setCanvasSize} from '../../utils/lib';
Scroll.prototype.update = function () {
this.adjustCanvas();
this.refresh();
this.bounceBack();
};
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
Scroll.prototype.addArrows = function (sc, w, h) {
this.aleft = newHTML('div', 'leftarrow', sc);
this.aleft.style.height = h + 'px';
var larrow = newHTML('span', undefined, this.aleft);
larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px';
this.aright = newHTML('div', 'rightarrow', sc);
this.aright.style.height = h + 'px';
var rarrow = newHTML('span', undefined, this.aright);
rarrow.style.top = Math.floor((h - rarrow.offsetHeight) / 2) + 'px';
this.aup = newHTML('div', 'toparrow', sc);
this.adown = newHTML('div', 'bottomarrow', sc);
newHTML('div', 'halign up', this.aup);
newHTML('div', 'halign down', this.adown);
var me = this;
if (isTablet) {
this.aup.ontouchstart = function (e) {
me.scrolldown(e);
};
} else {
this.aup.onmousedown = function (e) {
me.scrolldown(e);
};
export default class Scroll {
constructor (div, id, w, h, cfcn, ofcn) {
this.hasHorizontal = true;
this.hasVertical = true;
this.arrowDistance = 6;
this.aleft = undefined;
this.aright = undefined;
this.aup = undefined;
this.adown = undefined;
this.contents = newDiv(div, 0, 0, w, h, {});
this.contents.setAttribute('id', id);
this.contents.owner = this;
this.addArrows(div, w, h);
this.getContent = cfcn;
this.getObjects = ofcn;
div.scroll = this; // for now;
}
if (isTablet) {
this.adown.ontouchstart = function (e) {
me.scrollup(e);
};
} else {
this.adown.onmousedown = function (e) {
me.scrollup(e);
};
update () {
this.adjustCanvas();
this.refresh();
this.bounceBack();
}
if (isTablet) {
this.aleft.ontouchstart = function (e) {
me.scrollright(e);
};
} else {
this.aleft.onmousedown = function (e) {
me.scrollright(e);
};
}
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
if (isTablet) {
this.aright.ontouchstart = function (e) {
me.scrollleft(e);
};
} else {
this.aright.onmousedown = function (e) {
me.scrollleft(e);
};
}
addArrows (sc, w, h) {
this.aleft = newHTML('div', 'leftarrow', sc);
this.aleft.style.height = h + 'px';
var larrow = newHTML('span', undefined, this.aleft);
larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px';
};
this.aright = newHTML('div', 'rightarrow', sc);
this.aright.style.height = h + 'px';
var rarrow = newHTML('span', undefined, this.aright);
rarrow.style.top = Math.floor((h - rarrow.offsetHeight) / 2) + 'px';
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
this.aup = newHTML('div', 'toparrow', sc);
this.adown = newHTML('div', 'bottomarrow', sc);
newHTML('div', 'halign up', this.aup);
newHTML('div', 'halign down', this.adown);
Scroll.prototype.repositionArrows = function (h) {
this.aleft.style.height = h + 'px';
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px';
this.aright.style.height = h + 'px';
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px';
};
Scroll.prototype.getAdjustment = function (rect) { // rect of the dragg block canvas
var d = this.contents.parentNode; // scripts
var w = d.offsetWidth;
var h = d.offsetHeight;
if ((rect.x > 0) && (rect.y > 0)) {
return 'topleft';
}
if (((rect.x + rect.width) < w) && ((rect.y + rect.height) < h)) {
return 'bottomright';
}
if ((rect.x > 0) && ((rect.y + rect.height) < h)) {
return 'bottomleft';
}
if (((rect.x + rect.width) < w) && (rect.y > 0)) {
return 'topright';
}
if ((rect.x + rect.width) < w) {
return 'right';
}
if ((rect.y + rect.height) < h) {
return 'down';
}
if (rect.y > 0) {
return 'up';
}
if (rect.x > 0) {
return 'left';
}
return 'none';
};
Scroll.prototype.bounceBack = function () {
var owner = this;
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var valx = bc.left;
var valy = bc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: bc.offsetWidth,
height: bc.offsetHeight
};
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {},
onComplete: function () {
owner.refresh();
var me = this;
if (isTablet) {
this.aup.ontouchstart = function (e) {
me.scrolldown(e);
};
} else {
this.aup.onmousedown = function (e) {
me.scrolldown(e);
};
}
};
switch (this.getAdjustment(rect)) {
case 'topright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'topleft':
transition.style.top = '0px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomleft':
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'right':
transition.style.top = valy + 'px';
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'left':
if (this.hasHorizontal) {
transition.style.top = valy + 'px';
if (isTablet) {
this.adown.ontouchstart = function (e) {
me.scrollup(e);
};
} else {
this.adown.onmousedown = function (e) {
me.scrollup(e);
};
}
if (isTablet) {
this.aleft.ontouchstart = function (e) {
me.scrollright(e);
};
} else {
this.aleft.onmousedown = function (e) {
me.scrollright(e);
};
}
if (isTablet) {
this.aright.ontouchstart = function (e) {
me.scrollleft(e);
};
} else {
this.aright.onmousedown = function (e) {
me.scrollleft(e);
};
}
}
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
repositionArrows (h) {
this.aleft.style.height = h + 'px';
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px';
this.aright.style.height = h + 'px';
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px';
}
getAdjustment (rect) { // rect of the dragg block canvas
var d = this.contents.parentNode; // scripts
var w = d.offsetWidth;
var h = d.offsetHeight;
if ((rect.x > 0) && (rect.y > 0)) {
return 'topleft';
}
if (((rect.x + rect.width) < w) && ((rect.y + rect.height) < h)) {
return 'bottomright';
}
if ((rect.x > 0) && ((rect.y + rect.height) < h)) {
return 'bottomleft';
}
if (((rect.x + rect.width) < w) && (rect.y > 0)) {
return 'topright';
}
if ((rect.x + rect.width) < w) {
return 'right';
}
if ((rect.y + rect.height) < h) {
return 'down';
}
if (rect.y > 0) {
return 'up';
}
if (rect.x > 0) {
return 'left';
}
return 'none';
}
bounceBack () {
var owner = this;
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var valx = bc.left;
var valy = bc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: bc.offsetWidth,
height: bc.offsetHeight
};
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {},
onComplete: function () {
owner.refresh();
}
};
switch (this.getAdjustment(rect)) {
case 'topright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = '0px';
CSSTransition3D(bc, transition);
break;
case 'bottomright':
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'topleft':
transition.style.top = '0px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
}
break;
case 'down':
transition.style.top = (h - rect.height) + 'px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
break;
case 'up':
if (this.hasVertical) {
transition.style.top = '0px';
break;
case 'bottomleft':
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
break;
case 'right':
transition.style.top = valy + 'px';
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
CSSTransition3D(bc, transition);
break;
case 'left':
if (this.hasHorizontal) {
transition.style.top = valy + 'px';
transition.style.left = '0px';
CSSTransition3D(bc, transition);
}
break;
case 'down':
transition.style.top = (h - rect.height) + 'px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
break;
case 'up':
if (this.hasVertical) {
transition.style.top = '0px';
transition.style.left = valx + 'px';
CSSTransition3D(bc, transition);
}
break;
}
break;
}
};
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
Scroll.prototype.refresh = function () {
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth;
var h = p.offsetHeight;
var you;
var needleft = 'hidden';
var needright = 'hidden';
var needup = 'hidden';
var needdown = 'hidden';
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left + bc.left < 0) {
needleft = 'visible';
}
if ((you.left + you.offsetWidth + bc.left) > w) {
needright = 'visible';
}
if (you.top + bc.top + 10 < 0) {
needup = 'visible';
}
if ((you.top + you.offsetHeight + bc.top) > h) {
needdown = 'visible';
refresh () {
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth;
var h = p.offsetHeight;
var you;
var needleft = 'hidden';
var needright = 'hidden';
var needup = 'hidden';
var needdown = 'hidden';
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left + bc.left < 0) {
needleft = 'visible';
}
if ((you.left + you.offsetWidth + bc.left) > w) {
needright = 'visible';
}
if (you.top + bc.top + 10 < 0) {
needup = 'visible';
}
if ((you.top + you.offsetHeight + bc.top) > h) {
needdown = 'visible';
}
}
this.aleft.style.visibility = needleft;
this.aright.style.visibility = needright;
this.aup.style.visibility = needup;
this.adown.style.visibility = needdown;
}
this.aleft.style.visibility = needleft;
this.aright.style.visibility = needright;
this.aup.style.visibility = needup;
this.adown.style.visibility = needdown;
};
Scroll.prototype.adjustCanvas = function () {
var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer
var w = p.offsetWidth;
var h = p.offsetHeight;
var ow = bc.offsetWidth;
var oh = bc.offsetHeight;
var you;
var minx = 99999;
var maxwidth = 0;
var miny = 99999;
var maxheight = 0;
var padding = 0;
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
adjustCanvas () {
var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer
var w = p.offsetWidth;
var h = p.offsetHeight;
var ow = bc.offsetWidth;
var oh = bc.offsetHeight;
var you;
var minx = 99999;
var maxwidth = 0;
var miny = 99999;
var maxheight = 0;
var padding = 0;
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div;
if (you == null) {
continue;
}
if (!you.owner) {
continue;
}
if (you.style.visibility == 'hidden') {
continue;
}
if (you.left < minx) {
minx = you.left;
}
if ((you.left + you.offsetWidth + padding) > maxwidth) {
maxwidth = you.left + you.offsetWidth + padding;
}
if (you.top < miny) {
miny = you.top;
}
if ((you.top + you.offsetHeight + 20) > maxheight) {
maxheight = you.top + you.offsetHeight + 20;
}
}
if (!you.owner) {
continue;
if (minx < 0) {
minx -= padding;
minx += bc.left;
w -= minx;
} else {
minx = 0;
}
if (you.style.visibility == 'hidden') {
continue;
if (miny < 0) {
miny -= 20;
miny += bc.top;
h -= miny;
} else {
miny = 0;
}
if (you.left < minx) {
minx = you.left;
if ((maxwidth - minx) > w) {
w = Math.round(maxwidth - minx);
}
if ((you.left + you.offsetWidth + padding) > maxwidth) {
maxwidth = you.left + you.offsetWidth + padding;
if ((maxheight - miny) > h) {
h = Math.round(maxheight - miny);
}
if (you.top < miny) {
miny = you.top;
if ((ow != w) || (oh != h)) {
setCanvasSize(bc, w, h);
}
if ((you.top + you.offsetHeight + 20) > maxheight) {
maxheight = you.top + you.offsetHeight + 20;
if ((minx < 0) || (miny < 0)) {
this.moveBlocks(-minx, -miny);
Events.move3D(bc, minx, miny);
}
}
if (minx < 0) {
minx -= padding;
minx += bc.left;
w -= minx;
} else {
minx = 0;
}
if (miny < 0) {
miny -= 20;
miny += bc.top;
h -= miny;
} else {
miny = 0;
}
if ((maxwidth - minx) > w) {
w = Math.round(maxwidth - minx);
}
if ((maxheight - miny) > h) {
h = Math.round(maxheight - miny);
}
if ((ow != w) || (oh != h)) {
setCanvasSize(bc, w, h);
}
if ((minx < 0) || (miny < 0)) {
this.moveBlocks(-minx, -miny);
Events.move3D(bc, minx, miny);
}
};
Scroll.prototype.moveBlocks = function (dx, dy) {
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy);
}
};
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
Scroll.prototype.scrolldown = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top + h;
if (valy > 0) {
valy = 0;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
moveBlocks (dx, dy) {
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy);
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.scrollup = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top - h;
if ((valy + sc.offsetHeight) < h) {
valy = h - sc.offsetHeight;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
scrolldown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
};
CSSTransition3D(sc, transition);
};
Scroll.prototype.scrollright = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left + w;
if (valx > 0) {
valx = 0;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top + h;
if (valy > 0) {
valy = 0;
}
};
CSSTransition3D(sc, transition);
};
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
Scroll.prototype.scrollleft = function (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left - w;
if ((valx + sc.offsetWidth) < w) {
valx = w - sc.offsetWidth;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
scrollup (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
};
CSSTransition3D(sc, transition);
};
Scroll.prototype.fitToScreen = function () {
var p = this.contents;
var sc = this.getContent();
var valx = sc.left;
var valy = sc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: sc.offsetWidth,
height: sc.offsetHeight
};
switch (this.getAdjustment(rect)) {
case 'topright':
valx = w - rect.width;
valy = 0;
break;
case 'bottomright':
valx = w - rect.width;
valy = h - rect.height;
break;
case 'topleft':
valx = 0; valy = 0;
break;
case 'bottomleft':
valy = h - rect.height;
valx = 0;
break;
case 'right':
valx = w - rect.width;
break;
case 'left':
valx = 0;
break;
case 'down':
valy = h - rect.height;
break;
case 'up':
valy = 0;
break;
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var h = p.offsetHeight;
var valy = sc.top - h;
if ((valy + sc.offsetHeight) < h) {
valy = h - sc.offsetHeight;
}
valy = Math.round(valy);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
Events.move3D(sc, valx, valy);
};
scrollright (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left + w;
if (valx > 0) {
valx = 0;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
scrollleft (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
var owner = this;
var p = this.contents;
var sc = this.getContent();
var w = p.offsetWidth;
var valx = sc.left - w;
if ((valx + sc.offsetWidth) < w) {
valx = w - sc.offsetWidth;
}
valx = Math.round(valx);
var transition = {
duration: 0.5,
transition: 'ease-out',
style: {
left: valx + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
fitToScreen () {
var p = this.contents;
var sc = this.getContent();
var valx = sc.left;
var valy = sc.top;
var h = p.offsetHeight;
var w = p.offsetWidth;
var rect = {
x: valx,
y: valy,
width: sc.offsetWidth,
height: sc.offsetHeight
};
switch (this.getAdjustment(rect)) {
case 'topright':
valx = w - rect.width;
valy = 0;
break;
case 'bottomright':
valx = w - rect.width;
valy = h - rect.height;
break;
case 'topleft':
valx = 0; valy = 0;
break;
case 'bottomleft':
valy = h - rect.height;
valx = 0;
break;
case 'right':
valx = w - rect.width;
break;
case 'left':
valx = 0;
break;
case 'down':
valy = h - rect.height;
break;
case 'up':
valy = 0;
break;
}
Events.move3D(sc, valx, valy);
}
}