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 Argument types
@ -9,442 +18,448 @@ r: number for recorded sound block
p: page icons p: page icons
*/ */
var BlockArg = function (block) { export default class BlockArg {
this.daddy = block; constructor (block) {
this.type = 'blockarg'; this.daddy = block;
this.argType = block.spec[3]; this.type = 'blockarg';
switch (this.argType) { this.argType = block.spec[3];
case 'n': switch (this.argType) {
this.argValue = block.spec[4]; case 'n':
this.div = this.addNumArg(); this.argValue = block.spec[4];
break; this.div = this.addNumArg();
case 't': break;
this.argValue = block.spec[4]; case 't':
if (Localization.isSampleLocalizedKey(this.argValue) && ScratchJr.isSampleOrStarter()) { this.argValue = block.spec[4];
this.argValue = Localization.localize('SAMPLE_TEXT_' + this.argValue); 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 () { update () {
if (this.argType == 'r') { if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue; 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 () { getScreenPt () {
return { return {
x: globalx(this.daddy.div), x: globalx(this.daddy.div),
y: globaly(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);
}; };
} 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) { addNumArg () {
var div = newHTML('div', 'numfield', this.daddy.div); var str = this.argValue.toString();
if (this.daddy.blocktype == 'repeat') { if (this.daddy.inpalette) {
setProps(div.style, { return this.addLabel(str, false);
left: (this.daddy.blockshape.width / window.devicePixelRatio - 62 * this.daddy.scale) + 'px', } else {
top: (this.daddy.blockshape.height / window.devicePixelRatio - 11 * this.daddy.scale) + 'px' return this.addNumArgument(str);
});
}
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];
} }
} }
return list[0];
};
BlockArg.prototype.addImageMenu = function (fcn) { addTextArg () {
this.drawChoice(this.daddy.blockicon); var str = this.argValue.toString();
this.button = this.addPressButton(); if (this.daddy.inpalette) {
if (!this.daddy.inpalette) { return this.addLabel(str, true);
var ba = this; } else {
if (isTablet) { return this.addTextArgument(str, true);
ba.button.ontouchstart = function (evt) { }
ba.pressDropDown(evt, fcn); }
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 { } else {
ba.button.onmousedown = function (evt) { ctx.drawImage(img, 0, 0, w, h, 0, 0, w * window.devicePixelRatio, h * window.devicePixelRatio);
ba.pressDropDown(evt, fcn); }
}; 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, // Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button // else on Android 4.2 the bottom part of the button
// will not be clickable. // will not be clickable.
} div.parentNode.height += 10 * window.devicePixelRatio;
this.button.parentNode.height += this.button.height / 2; setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height); return div;
} }
return this.daddy.blockicon;
};
BlockArg.prototype.drawChoice = function (cnv) { addTextArgument (str) {
var ctx = cnv.getContext('2d'); var div = newHTML('div', 'textfield', this.daddy.div);
ctx.clearRect(0, 0, cnv.width, cnv.height); var ti = newHTML('h3', undefined, div);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg'); this.input = ti;
var scale = this.daddy.scale; ti.owner = this;
if (!icon.complete) { ti.textContent = str;
icon.onload = function () { 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, ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio, 0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio); icon.height * scale * window.devicePixelRatio);
}; }
} else { return cnv;
ctx.drawImage(icon, 0, 0, icon.width, icon.height,
0, 0, icon.width * scale * window.devicePixelRatio,
icon.height * scale * window.devicePixelRatio);
} }
return cnv;
};
BlockArg.prototype.addPressButton = function () { addPressButton () {
var scale = this.daddy.scale; var scale = this.daddy.scale;
var dx; var dx;
if (this.daddy.inpalette) { if (this.daddy.inpalette) {
dx = this.daddy.aStart ? 26 : 16; dx = this.daddy.aStart ? 26 : 16;
} else { } else {
dx = this.daddy.aStart ? 20 : 10; dx = this.daddy.aStart ? 20 : 10;
} }
var dy = 56; var dy = 56;
var w = (this.daddy.inpalette) ? 36 : 48; var w = (this.daddy.inpalette) ? 36 : 48;
var h = (this.daddy.inpalette) ? 20 : 27; var h = (this.daddy.inpalette) ? 20 : 27;
var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton; var img = (this.daddy.inpalette) ? BlockSpecs.pressbuttonSmall : BlockSpecs.pressbutton;
var field = newCanvas(this.daddy.div, dx, dy, w, h, { var field = newCanvas(this.daddy.div, dx, dy, w, h, {
position: 'absolute', position: 'absolute',
zoom: (scale * 100) + '%', zoom: (scale * 100) + '%',
pointerEvents: 'all', pointerEvents: 'all',
webkitTransform: 'translateZ(0)' webkitTransform: 'translateZ(0)'
}); });
var ctx = field.getContext('2d'); var ctx = field.getContext('2d');
if (!img.complete) { if (!img.complete) {
img.onload = function () { img.onload = function () {
ctx.drawImage(img, 0, 0);
};
} else {
ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0);
}; }
} else { return field;
ctx.drawImage(img, 0, 0);
} }
return field;
};
BlockArg.prototype.pressDropDown = function (e, fcn) { pressDropDown (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; 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) { closePictureMenu (e, mu, b, c) {
e.preventDefault(); e.preventDefault();
var value = b.owner.arg.argValue; var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length); b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d'); var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg'); b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio, 66 * scaleMultiplier * window.devicePixelRatio); ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio,
if (!b.icon.complete) { 66 * scaleMultiplier * window.devicePixelRatio);
b.icon.onload = function () { 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 w = b.icon.width;
var h = b.icon.height; var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0, ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, w * scaleMultiplier * window.devicePixelRatio,
h * scaleMultiplier * window.devicePixelRatio); h * scaleMultiplier * window.devicePixelRatio);
}; }
} else { if (Menu.openMenu) {
var w = b.icon.width; Menu.openMenu.parentNode.removeChild(Menu.openMenu);
var h = b.icon.height; }
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0, if (b.owner.arg.argValue != value) {
w * scaleMultiplier * window.devicePixelRatio, var spr = b.parentNode.owner.spr;
h * scaleMultiplier * window.devicePixelRatio); 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) { menuCloseSpeeds (e, mu, b, c) {
e.preventDefault(); e.preventDefault();
var value = b.owner.arg.argValue; var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c); b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d'); var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg'); b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio, 64 * scaleMultiplier * window.devicePixelRatio); ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio,
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM 64 * scaleMultiplier * window.devicePixelRatio);
b.owner.blockicon.style.display = 'none'; // On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.offsetHeight; b.owner.blockicon.style.display = 'none';
b.owner.blockicon.style.display = 'inherit'; b.owner.blockicon.offsetHeight;
if (!b.icon.complete) { b.owner.blockicon.style.display = 'inherit';
b.icon.onload = function () { 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 w = b.icon.width;
var h = b.icon.height; var h = b.icon.height;
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0, ctx.drawImage(b.icon, 0, 0, w, h, 0, 0,
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio); w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio);
}; }
} else { if (Menu.openMenu) {
var w = b.icon.width; Menu.openMenu.parentNode.removeChild(Menu.openMenu);
var h = b.icon.height; }
ctx.drawImage(b.icon, 0, 0, w, h, 0, 0, if (b.owner.arg.argValue != value) {
w * scaleMultiplier * window.devicePixelRatio, h * scaleMultiplier * window.devicePixelRatio); 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) { pageIcon (num) {
var dpr = window.devicePixelRatio; var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1]; var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas'); var icon = document.createElement('canvas');
setCanvasSize(icon, 86 * dpr, 66 * dpr); setCanvasSize(icon, 86 * dpr, 66 * dpr);
if (!page) { 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; 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 () { updateIcon () {
var num = this.argValue; var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1]; var page = ScratchJr.stage.pages[num - 1];
page.num = num; page.num = num;
this.div = this.pageIcon(num); this.div = this.pageIcon(num);
var block = this.daddy; var block = this.daddy;
var ctx = block.blockshape.getContext('2d'); var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0, ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale); 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 () { import ScratchJr from '../ScratchJr';
this.threadsRunning = []; import Project from '../../ui/Project';
this.thread = undefined; import Prims from './Prims';
this.intervalId = undefined; import Thread from './Thread';
this.yield = false;
};
Runtime.prototype.beginTimer = function () { export default class Runtime {
if (this.intervalId != null) { constructor () {
window.clearInterval(this.intervalId); 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 () { beginTimer () {
ScratchJr.updateRunStopButtons(); if (this.intervalId != null) {
if (this.threadsRunning.length < 1) { window.clearInterval(this.intervalId);
return;
}
var activeThreads = [];
for (var i = 0; i < this.threadsRunning.length; i++) {
if (this.threadsRunning[i].isRunning) {
activeThreads.push(this.threadsRunning[i]);
} }
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 () { tickTask () {
if (this.threadsRunning.length < 1) { ScratchJr.updateRunStopButtons();
return true; if (this.threadsRunning.length < 1) {
}
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) {
return; return;
} }
if (this.thread.waitTimer > 0) { var activeThreads = [];
this.thread.waitTimer += -1; for (var i = 0; i < this.threadsRunning.length; i++) {
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) {
if (this.threadsRunning[i].isRunning) { if (this.threadsRunning[i].isRunning) {
if (this.threadsRunning[i].thisblock != null) { activeThreads.push(this.threadsRunning[i]);
this.threadsRunning[i].endPrim(); }
}
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;
}
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
if (this.threadsRunning[i].oldblock != null) { if (this.threadsRunning[i].oldblock != null) {
this.threadsRunning[i].oldblock.unhighlight(); 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) { import Prims from './Prims';
this.firstBlock = block.findFirst(); import Grid from '../ui/Grid';
this.thisblock = block; import Vector from '../../geom/Vector';
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.clear = function () { export default class Thread {
this.stack = []; constructor (s, block) {
this.firstTime = true; this.firstBlock = block.findFirst();
this.count = -1; this.thisblock = block;
this.waitTimer = 0; this.oldblock = null;
this.vector = { this.spr = s;
x: 0, this.audio = undefined;
y: 0 this.stack = [];
}; this.firstTime = true;
this.distance = -1; this.count = -1;
this.called = []; this.waitTimer = 0;
this.thisblock = this.firstBlock; this.distance = -1;
}; this.called = [];
this.vector = {
Thread.prototype.duplicate = function () { x: 0,
var thread = new Thread(this.spr, this.firstBlock); y: 0
thread.count = -1; };
thread.firstBlock = this.firstBlock; this.isRunning = true;
thread.thisblock = this.thisblock; this.time = 0; // for debugging purposes
thread.oldblock = null; return this;
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;
} }
};
Thread.prototype.stop = function (b) { clear () {
this.stopping(b); this.stack = [];
this.isRunning = false; this.firstTime = true;
}; this.count = -1;
this.waitTimer = 0;
Thread.prototype.stopping = function (b) { this.vector = {
this.endPrim(b); x: 0,
this.deselect(this.firstBlock); y: 0
this.clear(); };
this.spr.closeBalloon(); this.distance = -1;
}; this.called = [];
this.thisblock = this.firstBlock;
Thread.prototype.endPrim = function (stopMine) {
if (!this.thisblock) {
return;
} }
var b = this.thisblock;
var s = this.spr; duplicate () {
switch (b.blocktype) { var thread = new Thread(this.spr, this.firstBlock);
case 'down': thread.count = -1;
case 'back': thread.firstBlock = this.firstBlock;
case 'forward': thread.thisblock = this.thisblock;
case 'up': thread.oldblock = null;
if ((this.distance > -1) && !stopMine) { thread.spr = this.spr;
var vector = Vector.scale(this.vector, this.distance % 24); thread.stack = this.stack;
s.setPos(s.xcoor + vector.x, s.ycoor + vector.y); thread.firstTime = this.firstTime;
} thread.vector = {
break; x: 0,
case 'hop': y: 0
var count = this.count; };
var n = Number(b.getArgValue()); thread.waitTimer = 0;
count--; thread.distance = -1;
if (count > 0) { thread.called = this.called;
var delta = 0; thread.isRunning = this.isRunning;
for (var i = count; i > -1; i--) { return thread;
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;
} }
};
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 // Scrolling Pane
//////////////////////////////////////////////// ////////////////////////////////////////////////
var Scroll = function (div, id, w, h, cfcn, ofcn) { import Events from '../../utils/Events';
this.hasHorizontal = true; import {newDiv, newHTML, CSSTransition3D, isTablet, setCanvasSize} from '../../utils/lib';
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;
};
Scroll.prototype.update = function () { export default class Scroll {
this.adjustCanvas(); constructor (div, id, w, h, cfcn, ofcn) {
this.refresh(); this.hasHorizontal = true;
this.bounceBack(); this.hasVertical = true;
}; this.arrowDistance = 6;
this.aleft = undefined;
///////////////////////////////////////////////////////////// this.aright = undefined;
// Arrows this.aup = undefined;
//////////////////////////////////////////////////////////// this.adown = undefined;
this.contents = newDiv(div, 0, 0, w, h, {});
Scroll.prototype.addArrows = function (sc, w, h) { this.contents.setAttribute('id', id);
this.aleft = newHTML('div', 'leftarrow', sc); this.contents.owner = this;
this.aleft.style.height = h + 'px'; this.addArrows(div, w, h);
var larrow = newHTML('span', undefined, this.aleft); this.getContent = cfcn;
larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px'; this.getObjects = ofcn;
div.scroll = this; // for now;
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);
};
} }
if (isTablet) { update () {
this.adown.ontouchstart = function (e) { this.adjustCanvas();
me.scrollup(e); this.refresh();
}; this.bounceBack();
} else {
this.adown.onmousedown = function (e) {
me.scrollup(e);
};
} }
if (isTablet) { /////////////////////////////////////////////////////////////
this.aleft.ontouchstart = function (e) { // Arrows
me.scrollright(e); ////////////////////////////////////////////////////////////
};
} else {
this.aleft.onmousedown = function (e) {
me.scrollright(e);
};
}
if (isTablet) { addArrows (sc, w, h) {
this.aright.ontouchstart = function (e) { this.aleft = newHTML('div', 'leftarrow', sc);
me.scrollleft(e); this.aleft.style.height = h + 'px';
}; var larrow = newHTML('span', undefined, this.aleft);
} else { larrow.style.top = Math.floor((h - larrow.offsetHeight) / 2) + 'px';
this.aright.onmousedown = function (e) {
me.scrollleft(e);
};
}
}; 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);
// Scrolling this.adown = newHTML('div', 'bottomarrow', sc);
//////////////////////////////////////////////////////////// newHTML('div', 'halign up', this.aup);
newHTML('div', 'halign down', this.adown);
Scroll.prototype.repositionArrows = function (h) { var me = this;
this.aleft.style.height = h + 'px'; if (isTablet) {
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px'; this.aup.ontouchstart = function (e) {
this.aright.style.height = h + 'px'; me.scrolldown(e);
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px'; };
}; } else {
this.aup.onmousedown = function (e) {
Scroll.prototype.getAdjustment = function (rect) { // rect of the dragg block canvas me.scrolldown(e);
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();
} }
};
switch (this.getAdjustment(rect)) { if (isTablet) {
case 'topright': this.adown.ontouchstart = function (e) {
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px'; me.scrollup(e);
transition.style.top = '0px'; };
CSSTransition3D(bc, transition); } else {
break; this.adown.onmousedown = function (e) {
case 'bottomright': me.scrollup(e);
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px'; };
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px'; }
CSSTransition3D(bc, transition);
break; if (isTablet) {
case 'topleft': this.aleft.ontouchstart = function (e) {
transition.style.top = '0px'; me.scrollright(e);
transition.style.left = '0px'; };
CSSTransition3D(bc, transition); } else {
break; this.aleft.onmousedown = function (e) {
case 'bottomleft': me.scrollright(e);
transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px'; };
transition.style.left = '0px'; }
CSSTransition3D(bc, transition);
break; if (isTablet) {
case 'right': this.aright.ontouchstart = function (e) {
transition.style.top = valy + 'px'; me.scrollleft(e);
transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px'; };
CSSTransition3D(bc, transition); } else {
break; this.aright.onmousedown = function (e) {
case 'left': me.scrollleft(e);
if (this.hasHorizontal) { };
transition.style.top = valy + 'px'; }
}
/////////////////////////////////////////////////////////////
// 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'; transition.style.left = '0px';
CSSTransition3D(bc, transition); CSSTransition3D(bc, transition);
} break;
break; case 'bottomleft':
case 'down': transition.style.top = (this.hasVertical ? h - rect.height : 0) + 'px';
transition.style.top = (h - rect.height) + 'px'; transition.style.left = '0px';
transition.style.left = valx + 'px'; CSSTransition3D(bc, transition);
CSSTransition3D(bc, transition); break;
break; case 'right':
case 'up': transition.style.top = valy + 'px';
if (this.hasVertical) { transition.style.left = (this.hasHorizontal ? (w - rect.width) : 0) + 'px';
transition.style.top = '0px'; 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'; transition.style.left = valx + 'px';
CSSTransition3D(bc, transition); 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 () { refresh () {
var p = this.contents; // scriptscontainer var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth; var w = p.offsetWidth;
var h = p.offsetHeight; var h = p.offsetHeight;
var you; var you;
var needleft = 'hidden'; var needleft = 'hidden';
var needright = 'hidden'; var needright = 'hidden';
var needup = 'hidden'; var needup = 'hidden';
var needdown = 'hidden'; var needdown = 'hidden';
var allblocks = this.getObjects(); var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) { for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div; you = allblocks[i].div;
if (you == null) { if (you == null) {
continue; continue;
} }
if (!you.owner) { if (!you.owner) {
continue; continue;
} }
if (you.style.visibility == 'hidden') { if (you.style.visibility == 'hidden') {
continue; continue;
} }
if (you.left + bc.left < 0) { if (you.left + bc.left < 0) {
needleft = 'visible'; needleft = 'visible';
} }
if ((you.left + you.offsetWidth + bc.left) > w) { if ((you.left + you.offsetWidth + bc.left) > w) {
needright = 'visible'; needright = 'visible';
} }
if (you.top + bc.top + 10 < 0) { if (you.top + bc.top + 10 < 0) {
needup = 'visible'; needup = 'visible';
} }
if ((you.top + you.offsetHeight + bc.top) > h) { if ((you.top + you.offsetHeight + bc.top) > h) {
needdown = 'visible'; 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 () { adjustCanvas () {
var bc = this.getContent(); // blockcanvas var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer var p = this.contents; // scriptscontainer
var w = p.offsetWidth; var w = p.offsetWidth;
var h = p.offsetHeight; var h = p.offsetHeight;
var ow = bc.offsetWidth; var ow = bc.offsetWidth;
var oh = bc.offsetHeight; var oh = bc.offsetHeight;
var you; var you;
var minx = 99999; var minx = 99999;
var maxwidth = 0; var maxwidth = 0;
var miny = 99999; var miny = 99999;
var maxheight = 0; var maxheight = 0;
var padding = 0; var padding = 0;
var allblocks = this.getObjects(); var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) { for (var i = 0; i < allblocks.length; i++) {
you = allblocks[i].div; you = allblocks[i].div;
if (you == null) { if (you == null) {
continue; 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) { if (minx < 0) {
continue; minx -= padding;
minx += bc.left;
w -= minx;
} else {
minx = 0;
} }
if (you.style.visibility == 'hidden') { if (miny < 0) {
continue; miny -= 20;
miny += bc.top;
h -= miny;
} else {
miny = 0;
} }
if (you.left < minx) { if ((maxwidth - minx) > w) {
minx = you.left; w = Math.round(maxwidth - minx);
} }
if ((you.left + you.offsetWidth + padding) > maxwidth) { if ((maxheight - miny) > h) {
maxwidth = you.left + you.offsetWidth + padding; h = Math.round(maxheight - miny);
} }
if (you.top < miny) { if ((ow != w) || (oh != h)) {
miny = you.top; setCanvasSize(bc, w, h);
} }
if ((you.top + you.offsetHeight + 20) > maxheight) { if ((minx < 0) || (miny < 0)) {
maxheight = you.top + you.offsetHeight + 20; 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) { moveBlocks (dx, dy) {
var allblocks = this.getObjects(); var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) { for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i]; var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy); 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();
} }
}; }
CSSTransition3D(sc, transition);
};
Scroll.prototype.scrollup = function (e) { /////////////////////////////////////////////////////////////
if (isTablet && e.touches && (e.touches.length > 1)) { // Scrolling
return; ////////////////////////////////////////////////////////////
}
e.preventDefault(); scrolldown (e) {
e.stopPropagation(); if (isTablet && e.touches && (e.touches.length > 1)) {
var owner = this; return;
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();
} }
}; e.preventDefault();
CSSTransition3D(sc, transition); e.stopPropagation();
}; var owner = this;
var p = this.contents;
Scroll.prototype.scrollright = function (e) { var sc = this.getContent();
if (isTablet && e.touches && (e.touches.length > 1)) { var h = p.offsetHeight;
return; var valy = sc.top + h;
} if (valy > 0) {
e.preventDefault(); valy = 0;
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();
} }
}; valy = Math.round(valy);
CSSTransition3D(sc, transition); var transition = {
}; duration: 0.5,
transition: 'ease-out',
style: {
top: valy + 'px'
},
onComplete: function () {
owner.refresh();
}
};
CSSTransition3D(sc, transition);
}
Scroll.prototype.scrollleft = function (e) { scrollup (e) {
if (isTablet && e.touches && (e.touches.length > 1)) { if (isTablet && e.touches && (e.touches.length > 1)) {
return; 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();
} }
}; e.preventDefault();
CSSTransition3D(sc, transition); e.stopPropagation();
}; var owner = this;
var p = this.contents;
Scroll.prototype.fitToScreen = function () { var sc = this.getContent();
var p = this.contents; var h = p.offsetHeight;
var sc = this.getContent(); var valy = sc.top - h;
var valx = sc.left; if ((valy + sc.offsetHeight) < h) {
var valy = sc.top; valy = h - sc.offsetHeight;
var h = p.offsetHeight; }
var w = p.offsetWidth; valy = Math.round(valy);
var rect = { var transition = {
x: valx, duration: 0.5,
y: valy, transition: 'ease-out',
width: sc.offsetWidth, style: {
height: sc.offsetHeight top: valy + 'px'
}; },
switch (this.getAdjustment(rect)) { onComplete: function () {
case 'topright': owner.refresh();
valx = w - rect.width; }
valy = 0; };
break; CSSTransition3D(sc, transition);
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);
}; 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);
}
}