mirror of
https://github.com/scratchfoundation/scratchjr.git
synced 2024-11-28 18:15:37 -05:00
Modules pass
This commit is contained in:
parent
f22472f8de
commit
41522cf4f1
12 changed files with 4793 additions and 906 deletions
40
.eslintrc
40
.eslintrc
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"strict": 0,
|
||||
"curly": [2, "multi-line"],
|
||||
"eol-last": [2],
|
||||
"indent": [2, 4],
|
||||
|
@ -20,42 +22,10 @@
|
|||
"AndroidInterface": true,
|
||||
"window": true,
|
||||
"Cookie": true,
|
||||
"getUrlVars": true,
|
||||
"libInit": true,
|
||||
"vlen": true,
|
||||
"gn": true,
|
||||
"CSSTransition": true,
|
||||
"CSSTransition3D": true,
|
||||
"WebKitCSSMatrix": true,
|
||||
"globalx": true,
|
||||
"globaly": true,
|
||||
"localx": true,
|
||||
"localy": true,
|
||||
"getIdFor": true,
|
||||
"hitRect": true,
|
||||
"hit3DRect": true,
|
||||
"rgb2hsb": true,
|
||||
"colorToRGBA": true,
|
||||
"drawScaled": true,
|
||||
"getDocumentHeight": true,
|
||||
"getDocumentWidth": true,
|
||||
"setCanvasSizeScaledToWindowDocumentHeight": true,
|
||||
"newHTML": true,
|
||||
"newCanvas": true,
|
||||
"newDiv": true,
|
||||
"newP": true,
|
||||
"newTextInput": true,
|
||||
"newImage": true,
|
||||
"getStringSize": true,
|
||||
"setCanvasSize": true,
|
||||
"setProps": true,
|
||||
"frame": true,
|
||||
"writeText": true,
|
||||
"fitInRect": true,
|
||||
"rgbToHex": true,
|
||||
"Vector": true,
|
||||
"DrawPath": true,
|
||||
"drawThumbnail": true,
|
||||
"ScratchJr": true,
|
||||
"Runtime": true,
|
||||
"Localization": true,
|
||||
|
@ -93,7 +63,6 @@
|
|||
"Lobby": true,
|
||||
"Samples": true,
|
||||
"Camera": true,
|
||||
"getIdForCamera": true,
|
||||
"Ghost": true,
|
||||
"Layers": true,
|
||||
"Paint": true,
|
||||
|
@ -106,14 +75,9 @@
|
|||
"Transform": true,
|
||||
"Layer": true,
|
||||
"Path": true,
|
||||
"DEGTOR": true,
|
||||
"xform": true,
|
||||
"selxform": true,
|
||||
"SVG2Canvas": true,
|
||||
"isTablet": true,
|
||||
"isiOS": true,
|
||||
"isAndroid": true,
|
||||
"scaleMultiplier": true,
|
||||
"JSZip": true,
|
||||
"Snap": true,
|
||||
"IntlMessageFormat": true,
|
||||
|
|
|
@ -11,23 +11,13 @@
|
|||
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/lib.js"></script>
|
||||
<script>
|
||||
preprocessAndLoadCss("css", "css/font.css");
|
||||
preprocessAndLoadCss("css", "css/base.css");
|
||||
preprocessAndLoadCss("css", "css/editor.css");
|
||||
preprocessAndLoadCss("css", "css/editorleftpanel.css");
|
||||
preprocessAndLoadCss("css", "css/editorstage.css");
|
||||
preprocessAndLoadCss("css", "css/editormodal.css");
|
||||
preprocessAndLoadCss("css", "css/librarymodal.css");
|
||||
preprocessAndLoadCss("css", "css/paintlook.css");
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Localization includes -->
|
||||
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
|
||||
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
|
||||
<script>
|
||||
Localization.includeLocales();
|
||||
</script>
|
||||
<!-- End localization includes -->
|
||||
|
||||
<script type="text/javascript" src="jssource/external/snap.svg-min.js"></script>
|
||||
|
@ -91,23 +81,8 @@
|
|||
<script type="text/javascript" src="jssource/painteditor/Layers.js"></script>
|
||||
<script type="text/javascript" src="jssource/painteditor/Ghost.js"></script>
|
||||
|
||||
<script language="javascript">
|
||||
|
||||
function createScratchJr(){
|
||||
iOS.getsettings(doNext);
|
||||
function doNext (str){
|
||||
var list = str.split(",");
|
||||
iOS.path =list[1] == "0" ? list[0] + "/" : undefined ;
|
||||
if (list.length > 2) Record.available = list[2] == "YES" ? true : false;
|
||||
if (list.length > 3) Camera.available = list[3] == "YES" ? true : false;
|
||||
ScratchJr.appinit(Settings.scratchJrVersion);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body onload="iOS.waitForInterface(createScratchJr);" style="background: white;">
|
||||
<body style="background: white;">
|
||||
<div class="frame" id="frame"></div>
|
||||
<div class="libframe" id="libframe"></div>
|
||||
<div class="paintframe" id="paintframe"></div>
|
||||
|
|
|
@ -10,24 +10,20 @@
|
|||
<head>
|
||||
<title>ScratchJr Intro</title>
|
||||
<script type="text/javascript" src="./Settings.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/lib.js"></script>
|
||||
<script type="text/javascript" src="jssource/build/bundles/index.bundle.js"></script>
|
||||
|
||||
<!--<script type="text/javascript" src="jssource/utils/Cookie.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/lib.js"></script>-->
|
||||
|
||||
<!-- Localization includes -->
|
||||
<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
|
||||
<!--<script type="text/javascript" src="jssource/external/Intl/Intl.min.js"></script>
|
||||
<script type="text/javascript" src="jssource/external/intl-messageformat/intl-messageformat.min.js"></script>
|
||||
<script type="text/javascript" src="jssource/utils/Localization.js"></script>
|
||||
<script>
|
||||
Localization.includeLocales();
|
||||
</script>
|
||||
</script>-->
|
||||
<!-- End localization includes -->
|
||||
|
||||
<script type="text/javascript">
|
||||
preprocessAndLoadCss("css", "css/font.css");
|
||||
preprocessAndLoadCss("css", "css/base.css");
|
||||
preprocessAndLoadCss("css", "css/start.css");
|
||||
preprocessAndLoadCss("css", "css/thumbs.css");
|
||||
</script>
|
||||
<!--
|
||||
<script type="text/javascript" src="jssource/utils/DrawPath.js"></script>
|
||||
<script type="text/javascript" src="jssource/editor/ui/Alert.js"></script>
|
||||
<script type="text/javascript" src="jssource/iPad/iOS.js"></script>
|
||||
|
@ -40,80 +36,21 @@
|
|||
<script type="text/javascript" src="jssource/painteditor/SVGImage.js"></script>
|
||||
<script type="text/javascript" src="jssource/painteditor/Transform.js"></script>
|
||||
<script type="text/javascript" src="jssource/painteditor/SVGTools.js"></script>
|
||||
<script type="text/javascript" src="jssource/geom/Rectangle.js"></script>
|
||||
|
||||
<script language="javascript">
|
||||
|
||||
function startup(){
|
||||
ScratchAudio.init();
|
||||
var urlvars = getUrlVars();
|
||||
if (urlvars["back"]) loadOptions();
|
||||
else firstTime();
|
||||
setTimeout(function(){gn('rays').className = "rays spinme";}, 250);
|
||||
}
|
||||
|
||||
function firstTime() {
|
||||
gn('authors').className = "credits show";
|
||||
gn('authorsText').className = "creditsText show";
|
||||
gn('purpleguy').className = "purple show";
|
||||
gn('blueguy').className = "blue show";
|
||||
gn('redguy').className = "red show";
|
||||
iOS.askpermission(); // ask for sound recording
|
||||
setTimeout(function(){iOS.hidesplash(doit);}, 500);
|
||||
function doit (str){
|
||||
ScratchAudio.sndFX("tap.wav");
|
||||
window.ontouchend = function () {loadOptions();};
|
||||
}
|
||||
setTimeout(function(){loadOptions();}, 2000);
|
||||
}
|
||||
|
||||
function loadOptions(){
|
||||
gn('authors').className = "credits hide";
|
||||
gn('authorsText').className = "creditsText hide";
|
||||
gn('purpleguy').className = "purple hide";
|
||||
gn('blueguy').className = "blue hide";
|
||||
gn('redguy').className = "red hide";
|
||||
gn('gettings').className = "gettings show";
|
||||
gn('startcode').className = "startcode show";
|
||||
document.ontouchmove = function(e){e.preventDefault()};
|
||||
if (isAndroid) AndroidInterface.notifySplashDone();
|
||||
}
|
||||
|
||||
function gohome(){
|
||||
rays.className = 'rays';
|
||||
// On iOS, sounds are loaded async, but the code as written expects to play tap.wav when we enter home.html
|
||||
// (but since it isn't loaded yet, no sound is played).
|
||||
// On Android, sync sounds means both calls to tap.wav result in a sound play.
|
||||
// XXX: we should re-write the lobby loading to wait for the sounds to load, and not play a sound here.
|
||||
if (isiOS) {
|
||||
ScratchAudio.sndFX("tap.wav");
|
||||
}
|
||||
iOS.setfile("homescroll.sjr", 0, function (str) {doNext()});
|
||||
function doNext() {window.location.href = "home.html";}
|
||||
}
|
||||
|
||||
function gettingstarted(){
|
||||
rays.className = 'rays';
|
||||
ScratchAudio.sndFX("tap.wav");
|
||||
window.location.href = "gettingstarted.html?place=home";
|
||||
}
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="jssource/geom/Rectangle.js"></script>-->
|
||||
|
||||
</head>
|
||||
<body onload="iOS.waitForInterface(startup);" style="margin:0px; background: black;">
|
||||
<div class="frame" id="frame">
|
||||
<div class="credits hide" id="authors"></div>
|
||||
<div class="creditsText hide" id="authorsText"></div>
|
||||
<div class="rays" id="rays"></div>
|
||||
<div class="catface"></div>
|
||||
<div class="jrlogo"></div>
|
||||
<div class="purple hide" id="purpleguy"></div>
|
||||
<div class="red hide" id="redguy"></div>
|
||||
<div class="blue hide" id="blueguy"></div>
|
||||
<div class="gettings hide" id="gettings" ontouchend="gettingstarted()"></div>
|
||||
<div class="startcode hide" id="startcode" ontouchend="gohome()"></div>
|
||||
</div>
|
||||
</div>
|
||||
<body style="margin:0px; background: black;">
|
||||
<div class="frame" id="frame">
|
||||
<div class="credits hide" id="authors"></div>
|
||||
<div class="creditsText hide" id="authorsText"></div>
|
||||
<div class="rays" id="rays"></div>
|
||||
<div class="catface"></div>
|
||||
<div class="jrlogo"></div>
|
||||
<div class="purple hide" id="purpleguy"></div>
|
||||
<div class="red hide" id="redguy"></div>
|
||||
<div class="blue hide" id="blueguy"></div>
|
||||
<div class="gettings hide" id="gettings"></div>
|
||||
<div class="startcode hide" id="startcode"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
15
package.json
15
package.json
|
@ -4,17 +4,26 @@
|
|||
"description": "ScratchJr",
|
||||
"private": "true",
|
||||
"scripts": {
|
||||
"lint": "eslint src/**"
|
||||
"lint": "eslint src/**",
|
||||
"build": "webpack"
|
||||
},
|
||||
"author": "MIT Media Lab",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.4.0",
|
||||
"babel-eslint": "^4.1.6",
|
||||
"babel-loader": "^6.2.1",
|
||||
"babel-preset-es2015": "^6.3.13",
|
||||
"esformatter": "^0.8.1",
|
||||
"esformatter-braces": "^1.2.1",
|
||||
"esformatter-dot-notation": "^1.3.1",
|
||||
"esformatter-quotes": "^1.0.3",
|
||||
"esformatter-semicolons": "^1.1.2",
|
||||
"eslint": "^1.10.3"
|
||||
"eslint": "^1.10.3",
|
||||
"webpack": "^1.12.11"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"intl": "^1.0.1",
|
||||
"intl-messageformat": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
|
819
src/build/bundles/editor.bundle.js
Normal file
819
src/build/bundles/editor.bundle.js
Normal file
|
@ -0,0 +1,819 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var _lib = __webpack_require__(1);
|
||||
|
||||
var _lib2 = _interopRequireDefault(_lib);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function createScratchJr() {
|
||||
iOS.getsettings(doNext);
|
||||
function doNext(str) {
|
||||
var list = str.split(',');
|
||||
iOS.path = list[1] == '0' ? list[0] + '/' : undefined;
|
||||
if (list.length > 2) {
|
||||
Record.available = list[2] == 'YES' ? true : false;
|
||||
}
|
||||
if (list.length > 3) {
|
||||
Camera.available = list[3] == 'YES' ? true : false;
|
||||
}
|
||||
ScratchJr.appinit(Settings.scratchJrVersion);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/font.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/base.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/editor.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/editorleftpanel.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/editorstage.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/editormodal.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/librarymodal.css');
|
||||
_lib2.default.preprocessAndLoadCss('css', 'css/paintlook.css');
|
||||
Localization.includeLocales();
|
||||
iOS.waitForInterface(createScratchJr);
|
||||
};
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var frame = exports.frame = undefined;
|
||||
// XXX: isTablet is legacy code that can be used to detect if we're running on a desktop browser
|
||||
// There are references to it throughout the codebase, should possibly be removed at some point
|
||||
var isTablet = exports.isTablet = window.orientation != 'undefined';
|
||||
var DEGTOR = exports.DEGTOR = Math.PI / 180;
|
||||
var WINDOW_INNER_HEIGHT = exports.WINDOW_INNER_HEIGHT = window.innerHeight;
|
||||
var WINDOW_INNER_WIDTH = exports.WINDOW_INNER_WIDTH = window.innerWidth;
|
||||
var scaleMultiplier = exports.scaleMultiplier = WINDOW_INNER_HEIGHT / 768.0;
|
||||
|
||||
var isiOS = exports.isiOS = typeof AndroidInterface == 'undefined';
|
||||
var isAndroid = exports.isAndroid = typeof AndroidInterface != 'undefined';
|
||||
|
||||
var Lib = function () {
|
||||
function Lib() {
|
||||
_classCallCheck(this, Lib);
|
||||
}
|
||||
|
||||
_createClass(Lib, null, [{
|
||||
key: 'libInit',
|
||||
value: function libInit() {
|
||||
exports.frame = frame = document.getElementById('frame');
|
||||
}
|
||||
/**
|
||||
* Takes a string and evaluates all ${} as JavaScript and returns the resulting string.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'preprocess',
|
||||
value: function preprocess(s) {
|
||||
var result = '';
|
||||
var len = s.length;
|
||||
var i = 0;
|
||||
var j;
|
||||
while (i < len && (j = s.indexOf('$', i)) != -1) {
|
||||
result += s.substring(i, j);
|
||||
i = j + 1;
|
||||
if (i < len - 1 && s[i] === '{') {
|
||||
var start = i + 1;
|
||||
var end = s.indexOf('}', start);
|
||||
if (end != -1) {
|
||||
var expression = s.substring(start, end);
|
||||
result += eval(expression);
|
||||
i = end + 1;
|
||||
} else {
|
||||
result += '$';
|
||||
}
|
||||
} else {
|
||||
result += '$';
|
||||
}
|
||||
}
|
||||
if (i < len) {
|
||||
result += s.substring(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the URL synchronously (fine because it's file://), preprocess the result and return the string.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'preprocessAndLoad',
|
||||
value: function preprocessAndLoad(url) {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('GET', url, false);
|
||||
xmlhttp.send();
|
||||
return this.preprocess(xmlhttp.responseText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a CSS file, preprocess it using preprocessAndLoad() and then returns it as a style tag.
|
||||
* Also rewrites all instances of url() with a different base
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'preprocessAndLoadCss',
|
||||
value: function preprocessAndLoadCss(baseUrl, url) {
|
||||
document.write('<!-- ' + url + '-->\n');
|
||||
document.write('<style type=\'text/css\'>\n');
|
||||
var cssData = this.preprocessAndLoad(url);
|
||||
cssData = cssData.replace(/url\('/g, 'url(\'' + baseUrl + '/');
|
||||
cssData = cssData.replace(/url\(([^'])/g, 'url(' + baseUrl + '/$1');
|
||||
document.write(cssData);
|
||||
document.write('\n</style>\n');
|
||||
}
|
||||
}, {
|
||||
key: 'rl',
|
||||
value: function rl() {
|
||||
window.location.reload();
|
||||
}
|
||||
}, {
|
||||
key: 'newDiv',
|
||||
value: function newDiv(parent, x, y, w, h, styles) {
|
||||
var el = document.createElement('div');
|
||||
el.style.position = 'absolute';
|
||||
el.style.top = y + 'px';
|
||||
el.style.left = x + 'px';
|
||||
if (w) {
|
||||
el.style.width = w + 'px';
|
||||
}
|
||||
if (h) {
|
||||
el.style.height = h + 'px';
|
||||
}
|
||||
this.setProps(el.style, styles);
|
||||
parent.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
}, {
|
||||
key: 'newImage',
|
||||
value: function newImage(parent, src, styles) {
|
||||
var img = document.createElement('img');
|
||||
img.src = src;
|
||||
this.setProps(img.style, styles);
|
||||
if (parent) {
|
||||
parent.appendChild(img);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
}, {
|
||||
key: 'newCanvas',
|
||||
value: function newCanvas(parent, x, y, w, h, styles) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.top = y + 'px';
|
||||
canvas.style.left = x + 'px';
|
||||
this.setCanvasSize(canvas, w, h);
|
||||
this.setProps(canvas.style, styles);
|
||||
parent.appendChild(canvas);
|
||||
return canvas;
|
||||
}
|
||||
}, {
|
||||
key: 'newHTML',
|
||||
value: function newHTML(type, c, p) {
|
||||
var e = document.createElement(type);
|
||||
if (c) {
|
||||
e.setAttribute('class', c);
|
||||
}
|
||||
if (p) {
|
||||
p.appendChild(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}, {
|
||||
key: 'newP',
|
||||
value: function newP(parent, text, styles) {
|
||||
var p = document.createElement('p');
|
||||
p.appendChild(document.createTextNode(text));
|
||||
this.setProps(p.style, styles);
|
||||
parent.appendChild(p);
|
||||
return p;
|
||||
}
|
||||
}, {
|
||||
key: 'hitRect',
|
||||
value: function hitRect(c, pt) {
|
||||
if (!pt) {
|
||||
return false;
|
||||
}
|
||||
if (!c) {
|
||||
return false;
|
||||
}
|
||||
var x = pt.x;
|
||||
var y = pt.y;
|
||||
if (c.offsetLeft == undefined) {
|
||||
return false;
|
||||
}
|
||||
if (c.offsetTop == undefined) {
|
||||
return false;
|
||||
}
|
||||
if (x < c.offsetLeft) {
|
||||
return false;
|
||||
}
|
||||
if (x > c.offsetLeft + c.offsetWidth) {
|
||||
return false;
|
||||
}
|
||||
if (y < c.offsetTop) {
|
||||
return false;
|
||||
}
|
||||
if (y > c.offsetTop + c.offsetHeight) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
key: 'hit3DRect',
|
||||
value: function hit3DRect(c, pt) {
|
||||
if (!pt) {
|
||||
return;
|
||||
}
|
||||
var x = pt.x;
|
||||
var y = pt.y;
|
||||
var mtx = new WebKitCSSMatrix(window.getComputedStyle(c).webkitTransform);
|
||||
if (mtx.m41 == undefined) {
|
||||
return false;
|
||||
}
|
||||
if (mtx.m42 == undefined) {
|
||||
return false;
|
||||
}
|
||||
if (x < mtx.m41) {
|
||||
return false;
|
||||
}
|
||||
if (x > mtx.m41 + c.offsetWidth) {
|
||||
return false;
|
||||
}
|
||||
if (y < mtx.m42) {
|
||||
return false;
|
||||
}
|
||||
if (y > mtx.m42 + c.offsetHeight) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
key: 'hitTest',
|
||||
value: function hitTest(c, pt) {
|
||||
if (!pt) {
|
||||
return;
|
||||
}
|
||||
var x = pt.x;
|
||||
var y = pt.y;
|
||||
if (x < c.offsetLeft) {
|
||||
return false;
|
||||
}
|
||||
if (x > c.offsetLeft + c.offsetWidth) {
|
||||
return false;
|
||||
}
|
||||
if (y < c.offsetTop) {
|
||||
return false;
|
||||
}
|
||||
if (y > c.offsetTop + c.offsetHeight) {
|
||||
return false;
|
||||
}
|
||||
var dx = pt.x - c.offsetLeft,
|
||||
dy = pt.y - c.offsetTop;
|
||||
var ctx = c.getContext('2d');
|
||||
var pixel = ctx.getImageData(dx, dy, 1, 1).data;
|
||||
if (pixel[3] == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
key: 'setCanvasSize',
|
||||
value: function setCanvasSize(c, w, h) {
|
||||
c.width = w;
|
||||
c.height = h;
|
||||
c.style.width = w + 'px';
|
||||
c.style.height = h + 'px';
|
||||
}
|
||||
}, {
|
||||
key: 'setCanvasSizeScaledToWindowDocumentHeight',
|
||||
value: function setCanvasSizeScaledToWindowDocumentHeight(c, w, h) {
|
||||
var multiplier = window.devicePixelRatio * scaleMultiplier;
|
||||
var scaledWidth = Math.floor(w * multiplier);
|
||||
var scaledHeight = Math.floor(h * multiplier);
|
||||
c.width = scaledWidth;
|
||||
c.height = scaledHeight;
|
||||
c.style.width = scaledWidth + 'px';
|
||||
c.style.height = scaledHeight + 'px';
|
||||
c.style.zoom = scaleMultiplier / multiplier;
|
||||
}
|
||||
}, {
|
||||
key: 'localx',
|
||||
value: function localx(el, gx) {
|
||||
var lx = gx;
|
||||
while (el && el.offsetTop != undefined) {
|
||||
lx -= el.offsetLeft + el.clientLeft + new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform).m41;
|
||||
el = el.parentNode;
|
||||
}
|
||||
return lx;
|
||||
}
|
||||
}, {
|
||||
key: 'globalx',
|
||||
value: function globalx(el) {
|
||||
var lx = 0;
|
||||
while (el && el.offsetLeft != undefined) {
|
||||
var webkitTransform = new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform);
|
||||
var transformScale = webkitTransform.m11;
|
||||
lx += (el.clientWidth - transformScale * el.clientWidth) / 2;
|
||||
var transformX = webkitTransform.m41;
|
||||
lx += transformX;
|
||||
lx += el.offsetLeft + el.clientLeft;
|
||||
el = el.parentNode;
|
||||
}
|
||||
return lx;
|
||||
}
|
||||
}, {
|
||||
key: 'localy',
|
||||
value: function localy(el, gy) {
|
||||
var ly = gy;
|
||||
while (el && el.offsetTop != undefined) {
|
||||
ly -= el.offsetTop + el.clientTop + new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform).m42;
|
||||
el = el.parentNode;
|
||||
}
|
||||
return ly;
|
||||
}
|
||||
}, {
|
||||
key: 'globaly',
|
||||
value: function globaly(el) {
|
||||
var ly = 0;
|
||||
while (el && el.offsetTop != undefined) {
|
||||
var webkitTransform = new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform);
|
||||
var transformScale = webkitTransform.m22;
|
||||
ly += (el.clientHeight - transformScale * el.clientHeight) / 2;
|
||||
var transformY = webkitTransform.m42;
|
||||
ly += transformY;
|
||||
ly += el.offsetTop + el.clientTop;
|
||||
el = el.parentNode;
|
||||
}
|
||||
return ly;
|
||||
}
|
||||
}, {
|
||||
key: 'setProps',
|
||||
value: function setProps(object, props) {
|
||||
for (var i in props) {
|
||||
object[i] = props[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ["ease", "linear", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end"];
|
||||
|
||||
}, {
|
||||
key: 'CSSTransition',
|
||||
value: function CSSTransition(el, obj) {
|
||||
// default
|
||||
var duration = 1;
|
||||
var transition = 'ease';
|
||||
var style = {
|
||||
left: el.offsetLeft + 'px',
|
||||
top: el.offsetTop + 'px'
|
||||
};
|
||||
if (obj.duration) {
|
||||
duration = obj.duration;
|
||||
}
|
||||
if (obj.transition) {
|
||||
transition = obj.transition;
|
||||
}
|
||||
if (obj.style) {
|
||||
style = obj.style;
|
||||
}
|
||||
var items = '';
|
||||
for (var key in style) {
|
||||
items += key + ' ' + duration + 's ' + transition + ', ';
|
||||
}
|
||||
items = items.substring(0, items.length - 2);
|
||||
el.style.webkitTransition = items;
|
||||
el.addEventListener('webkitTransitionEnd', transitionDene, true);
|
||||
this.setProps(el.style, style);
|
||||
function transitionDene() {
|
||||
el.style.webkitTransition = '';
|
||||
if (obj.onComplete) {
|
||||
obj.onComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: 'CSSTransition3D',
|
||||
value: function CSSTransition3D(el, obj) {
|
||||
// default
|
||||
var duration = 1;
|
||||
var transition = 'ease';
|
||||
var style = {
|
||||
left: el.left + 'px',
|
||||
top: el.top + 'px'
|
||||
}; // keepit where it is
|
||||
if (obj.duration) {
|
||||
duration = obj.duration;
|
||||
}
|
||||
if (obj.transition) {
|
||||
transition = obj.transition;
|
||||
}
|
||||
if (obj.style) {
|
||||
for (var key in obj.style) {
|
||||
style[key] = obj.style[key];
|
||||
}
|
||||
}
|
||||
var items = '-webkit-transform ' + duration + 's ' + transition;
|
||||
var translate = 'translate3d(' + style.left + ',' + style.top + ',0px)';
|
||||
el.addEventListener('webkitTransitionEnd', transitionDone, true);
|
||||
el.style.webkitTransition = items;
|
||||
el.style.webkitTransform = translate;
|
||||
function transitionDone() {
|
||||
el.style.webkitTransition = '';
|
||||
var mtx = new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform);
|
||||
el.left = mtx.m41;
|
||||
el.top = mtx.m42;
|
||||
if (obj.onComplete) {
|
||||
obj.onComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: 'drawThumbnail',
|
||||
value: function drawThumbnail(img, c) {
|
||||
// naturalWidth Height it gets the zoom scaling properly
|
||||
var w = img.naturalWidth ? img.naturalWidth : img.width;
|
||||
var h = img.naturalHeight ? img.naturalHeight : img.height;
|
||||
var dx = (c.width - w) / 2;
|
||||
var dy = (c.height - h) / 2;
|
||||
var dw = c.width / w;
|
||||
var dh = c.height / h;
|
||||
var wi = w;
|
||||
var he = h;
|
||||
switch (this.getFit(dw, dh)) {
|
||||
case 'noscale':
|
||||
break;
|
||||
case 'scaleh':
|
||||
wi = w * dh;
|
||||
he = h * dh;
|
||||
dx = (c.width - wi) / 2;
|
||||
dy = (c.height - he) / 2;
|
||||
break;
|
||||
case 'scalew':
|
||||
wi = w * dw;
|
||||
he = h * dw;
|
||||
dx = (c.width - wi) / 2;
|
||||
dy = (c.height - he) / 2;
|
||||
break;
|
||||
}
|
||||
var ctx = c.getContext('2d');
|
||||
ctx.drawImage(img, dx, dy, wi, he);
|
||||
}
|
||||
|
||||
// Like drawThumbnail, but scales up if needed
|
||||
|
||||
}, {
|
||||
key: 'drawScaled',
|
||||
value: function drawScaled(img, c) {
|
||||
var imgWidth = img.naturalWidth ? img.naturalWidth : img.width;
|
||||
var imgHeight = img.naturalHeight ? img.naturalHeight : img.height;
|
||||
var boxWidth = c.width;
|
||||
var boxHeight = c.height;
|
||||
var scale = boxWidth / imgWidth;
|
||||
var w = imgWidth * scale;
|
||||
var h = imgHeight * scale;
|
||||
if (h > boxHeight) {
|
||||
scale = boxHeight / imgHeight;
|
||||
w = imgWidth * scale;
|
||||
h = imgHeight * scale;
|
||||
}
|
||||
var x0 = (boxWidth - w) / 2;
|
||||
var y0 = (boxHeight - h) / 2;
|
||||
var ctx = c.getContext('2d');
|
||||
ctx.drawImage(img, x0, y0, w, h);
|
||||
}
|
||||
}, {
|
||||
key: 'fitInRect',
|
||||
value: function fitInRect(srcw, srch, destw, desth) {
|
||||
var dx = (destw - srcw) / 2;
|
||||
var dy = (desth - srch) / 2;
|
||||
var dw = destw / srcw;
|
||||
var dh = desth / srch;
|
||||
var wi = srcw;
|
||||
var he = srch;
|
||||
switch (this.getFit(dw, dh)) {
|
||||
case 'noscale':
|
||||
break;
|
||||
case 'scaleh':
|
||||
wi = srcw * dh;
|
||||
he = srch * dh;
|
||||
dx = (destw - wi) / 2;
|
||||
dy = (desth - he) / 2;
|
||||
break;
|
||||
case 'scalew':
|
||||
wi = srcw * dw;
|
||||
he = srch * dw;
|
||||
dx = (destw - wi) / 2;
|
||||
dy = (desth - he) / 2;
|
||||
break;
|
||||
}
|
||||
return [dx, dy, wi, he];
|
||||
}
|
||||
}, {
|
||||
key: 'getFit',
|
||||
value: function getFit(dw, dh) {
|
||||
if (dw >= 1 && dh >= 1) {
|
||||
return 'noscale';
|
||||
}
|
||||
if (dw >= 1 && dh < 1) {
|
||||
return 'scaleh';
|
||||
}
|
||||
if (dw < 1 && dh >= 1) {
|
||||
return 'scalew';
|
||||
}
|
||||
if (dw < dh) {
|
||||
return 'scalew';
|
||||
}
|
||||
return 'scaleh';
|
||||
}
|
||||
}, {
|
||||
key: 'getDocumentHeight',
|
||||
value: function getDocumentHeight() {
|
||||
return Math.max(document.body.clientHeight, document.documentElement.clientHeight);
|
||||
}
|
||||
}, {
|
||||
key: 'getDocumentWidth',
|
||||
value: function getDocumentWidth() {
|
||||
return Math.max(document.body.clientWidth, document.documentElement.clientWidth);
|
||||
}
|
||||
}, {
|
||||
key: 'getStringSize',
|
||||
value: function getStringSize(ctx, f, label) {
|
||||
ctx.font = f;
|
||||
return ctx.measureText(label);
|
||||
}
|
||||
}, {
|
||||
key: 'writeText',
|
||||
value: function writeText(ctx, f, c, label, dy, dx) {
|
||||
dx = dx == undefined ? 0 : dx;
|
||||
ctx.font = f;
|
||||
ctx.fillStyle = c;
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillText(label, dx, dy);
|
||||
}
|
||||
}, {
|
||||
key: 'gn',
|
||||
value: function gn(str) {
|
||||
return document.getElementById(str);
|
||||
}
|
||||
}, {
|
||||
key: 'newForm',
|
||||
value: function newForm(parent, str, x, y, w, h, styles) {
|
||||
var el = document.createElement('form');
|
||||
el.style.position = 'absolute';
|
||||
el.style.top = y + 'px';
|
||||
el.style.left = x + 'px';
|
||||
if (w) {
|
||||
el.style.width = w + 'px';
|
||||
}
|
||||
if (h) {
|
||||
el.style.height = h + 'px';
|
||||
}
|
||||
this.setProps(el.style, styles);
|
||||
parent.appendChild(el);
|
||||
el.name = str;
|
||||
return el;
|
||||
}
|
||||
}, {
|
||||
key: 'newTextInput',
|
||||
value: function newTextInput(p, type, str, mstyle) {
|
||||
var input = document.createElement('input');
|
||||
input.value = str;
|
||||
this.setProps(input.style, mstyle);
|
||||
input.type = type;
|
||||
p.appendChild(input);
|
||||
return input;
|
||||
}
|
||||
}, {
|
||||
key: 'getUrlVars',
|
||||
value: function getUrlVars() {
|
||||
if (window.location.href.indexOf('?') < 0) {
|
||||
return [];
|
||||
}
|
||||
var args = window.location.href.slice(window.location.href.indexOf('?') + 1);
|
||||
var vars = [],
|
||||
hash;
|
||||
var hashes = args.split('&');
|
||||
for (var i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i].split('=');
|
||||
vars.push(hash[0]);
|
||||
vars[hash[0]] = hash[1];
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
}, {
|
||||
key: 'getIdFor',
|
||||
value: function getIdFor(name) {
|
||||
var n = 1;
|
||||
while (this.gn(name + ' ' + n) != undefined) {
|
||||
n++;
|
||||
}
|
||||
return name + ' ' + n;
|
||||
}
|
||||
}, {
|
||||
key: 'getIdForCamera',
|
||||
value: function getIdForCamera(name) {
|
||||
var n = 1;
|
||||
while (this.gn(name + '_' + n) != undefined) {
|
||||
n++;
|
||||
}
|
||||
return name + '_' + n;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Color
|
||||
/////////////////////
|
||||
|
||||
}, {
|
||||
key: 'rgb2hsb',
|
||||
value: function rgb2hsb(str) {
|
||||
if (str == null) {
|
||||
return [24, 1, 1];
|
||||
}
|
||||
var min, val, f, i, hue, sat;
|
||||
str = str.indexOf('rgb') > -1 ? this.rgbToHex(str) : this.rgbaToHex(str);
|
||||
var num = parseInt(str.substring(1, str.length), 16);
|
||||
var rgb = this.getRGB(num);
|
||||
var red = rgb[0];
|
||||
red /= 255;
|
||||
var grn = rgb[1];
|
||||
grn /= 255;
|
||||
var blu = rgb[2];
|
||||
blu /= 255;
|
||||
min = Math.min(Math.min(red, grn), blu);
|
||||
val = Math.max(Math.max(red, grn), blu);
|
||||
if (min == val) {
|
||||
return new Array(0, 0, val);
|
||||
}
|
||||
f = red == min ? grn - blu : grn == min ? blu - red : red - grn;
|
||||
i = red == min ? 3 : grn == min ? 5 : 1;
|
||||
hue = Math.round((i - f / (val - min)) * 60) % 360;
|
||||
sat = Math.round((val - min) / val * 100);
|
||||
val = Math.round(val * 100);
|
||||
return new Array(hue, sat / 100, val / 100);
|
||||
}
|
||||
}, {
|
||||
key: 'rgbToHex',
|
||||
value: function rgbToHex(str) {
|
||||
if (str.indexOf('rgb') < 0) {
|
||||
return str;
|
||||
}
|
||||
var res = str.substring(4, str.length - 1);
|
||||
var a = res.split(',');
|
||||
var red = Number(a[0]);
|
||||
var grn = Number(a[1]);
|
||||
var blu = Number(a[2]);
|
||||
return this.rgbToString({
|
||||
r: red,
|
||||
g: grn,
|
||||
b: blu
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'rgbaToHex',
|
||||
value: function rgbaToHex(str) {
|
||||
if (str.indexOf('rgba') < 0) {
|
||||
return str;
|
||||
}
|
||||
var res = str.substring(5, str.length - 1);
|
||||
var a = res.split(',');
|
||||
var red = Number(a[0]);
|
||||
var grn = Number(a[1]);
|
||||
var blu = Number(a[2]);
|
||||
return this.rgbToString({
|
||||
r: red,
|
||||
g: grn,
|
||||
b: blu
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'rgbToString',
|
||||
value: function rgbToString(obj) {
|
||||
return '#' + this.getHex(obj.r) + this.getHex(obj.g) + this.getHex(obj.b);
|
||||
}
|
||||
}, {
|
||||
key: 'getRGB',
|
||||
value: function getRGB(color) {
|
||||
return [Number(color >> 16 & 255), Number(color >> 8 & 255), Number(color & 255)];
|
||||
}
|
||||
}, {
|
||||
key: 'getHex',
|
||||
value: function getHex(num) {
|
||||
var hex = num.toString(16);
|
||||
if (hex.length == 1) {
|
||||
return '0' + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
// findKeyframesRule ("swing");
|
||||
|
||||
}, {
|
||||
key: 'findKeyframesRule',
|
||||
value: function findKeyframesRule(rule) {
|
||||
var ss = document.styleSheets;
|
||||
for (var i = 0; i < ss.length; ++i) {
|
||||
for (var j = 0; j < ss[i].cssRules.length; ++j) {
|
||||
var styles = ss[i].cssRules[j].styleSheet.rules;
|
||||
for (var k = 0; k < styles.length; ++k) {
|
||||
if (styles[k].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && styles[k].name == rule) {
|
||||
return styles[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
} // rule not found
|
||||
return null;
|
||||
}
|
||||
}, {
|
||||
key: 'colorToRGBA',
|
||||
value: function colorToRGBA(color, opacity) {
|
||||
var val = parseInt('0x' + color.substr(1, color.length));
|
||||
return 'rgba(' + (val >> 16) % 256 + ',' + (val >> 8) % 256 + ',' + val % 256 + ',' + opacity + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* css units vh and vw (for % of height and width) are not supported in Android 4.3 and earlier, so
|
||||
* here we introduce functioncs (called from the preprocessed css) that emulate their behavior by
|
||||
* turning them into pixel values.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'css_vh',
|
||||
value: function css_vh(y) {
|
||||
return y * WINDOW_INNER_HEIGHT / 100.0 + 'px';
|
||||
}
|
||||
}, {
|
||||
key: 'css_vw',
|
||||
value: function css_vw(x) {
|
||||
return x * WINDOW_INNER_WIDTH / 100.0 + 'px';
|
||||
}
|
||||
}]);
|
||||
|
||||
return Lib;
|
||||
}();
|
||||
|
||||
exports.default = Lib;
|
||||
|
||||
Number.prototype.mod = function (n) {
|
||||
return (this % n + n) % n;
|
||||
};
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
3068
src/build/bundles/index.bundle.js
Normal file
3068
src/build/bundles/index.bundle.js
Normal file
File diff suppressed because it is too large
Load diff
29
src/entry/editor.js
Normal file
29
src/entry/editor.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import Lib from '../utils/lib';
|
||||
|
||||
function createScratchJr () {
|
||||
iOS.getsettings(doNext);
|
||||
function doNext (str) {
|
||||
var list = str.split(',');
|
||||
iOS.path = list[1] == '0' ? list[0] + '/' : undefined;
|
||||
if (list.length > 2) {
|
||||
Record.available = list[2] == 'YES' ? true : false;
|
||||
}
|
||||
if (list.length > 3) {
|
||||
Camera.available = list[3] == 'YES' ? true : false;
|
||||
}
|
||||
ScratchJr.appinit(Settings.scratchJrVersion);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
Lib.preprocessAndLoadCss('css', 'css/font.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/base.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/editor.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/editorleftpanel.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/editorstage.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/editormodal.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/librarymodal.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/paintlook.css');
|
||||
Localization.includeLocales();
|
||||
iOS.waitForInterface(createScratchJr);
|
||||
};
|
85
src/entry/index.js
Normal file
85
src/entry/index.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
import {Lib, isAndroid, isiOS} from '../utils/lib';
|
||||
import Localization from '../utils/Localization';
|
||||
|
||||
function startup () {
|
||||
ScratchAudio.init();
|
||||
var urlvars = Lib.getUrlVars();
|
||||
if (urlvars.back) {
|
||||
loadOptions();
|
||||
} else {
|
||||
firstTime();
|
||||
}
|
||||
setTimeout(function () {
|
||||
Lib.gn('rays').className = 'rays spinme';
|
||||
}, 250);
|
||||
}
|
||||
|
||||
function firstTime () {
|
||||
Lib.gn('authors').className = 'credits show';
|
||||
Lib.gn('authorsText').className = 'creditsText show';
|
||||
Lib.gn('purpleguy').className = 'purple show';
|
||||
Lib.gn('blueguy').className = 'blue show';
|
||||
Lib.gn('redguy').className = 'red show';
|
||||
iOS.askpermission(); // ask for sound recording
|
||||
setTimeout(function () {
|
||||
iOS.hidesplash(doit);
|
||||
}, 500);
|
||||
function doit () {
|
||||
ScratchAudio.sndFX('tap.wav');
|
||||
window.ontouchend = function () {
|
||||
loadOptions();
|
||||
};
|
||||
}
|
||||
setTimeout(function () {
|
||||
loadOptions();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function loadOptions () {
|
||||
Lib.gn('authors').className = 'credits hide';
|
||||
Lib.gn('authorsText').className = 'creditsText hide';
|
||||
Lib.gn('purpleguy').className = 'purple hide';
|
||||
Lib.gn('blueguy').className = 'blue hide';
|
||||
Lib.gn('redguy').className = 'red hide';
|
||||
Lib.gn('gettings').className = 'gettings show';
|
||||
Lib.gn('startcode').className = 'startcode show';
|
||||
document.ontouchmove = function (e) {
|
||||
e.preventDefault();
|
||||
};
|
||||
if (isAndroid) {
|
||||
AndroidInterface.notifySplashDone();
|
||||
}
|
||||
}
|
||||
|
||||
function gohome () {
|
||||
// On iOS, sounds are loaded async, but the code as written expects to play tap.wav when we enter home.html
|
||||
// (but since it isn't loaded yet, no sound is played).
|
||||
// On Android, sync sounds means both calls to tap.wav result in a sound play.
|
||||
// XXX: we should re-write the lobby loading to wait for the sounds to load, and not play a sound here.
|
||||
if (isiOS) {
|
||||
ScratchAudio.sndFX('tap.wav');
|
||||
}
|
||||
iOS.setfile('homescroll.sjr', 0, function () {
|
||||
doNext();
|
||||
});
|
||||
function doNext () {
|
||||
window.location.href = 'home.html';
|
||||
}
|
||||
}
|
||||
|
||||
function gettingstarted () {
|
||||
ScratchAudio.sndFX('tap.wav');
|
||||
window.location.href = 'gettingstarted.html?place=home';
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
Localization.includeLocales();
|
||||
Lib.preprocessAndLoadCss('css', 'css/font.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/base.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/start.css');
|
||||
Lib.preprocessAndLoadCss('css', 'css/thumbs.css');
|
||||
Lib.gn('gettings').ontouchend = gettingstarted;
|
||||
Lib.gn('startcode').ontouchend = gohome;
|
||||
|
||||
iOS.waitForInterface(startup);
|
||||
};
|
|
@ -1,24 +1,24 @@
|
|||
var Cookie = {};
|
||||
|
||||
// Thanks to http://www.quirksmode.org/js/cookies.html
|
||||
Cookie.set = function (key, value) {
|
||||
var year = new Date();
|
||||
year.setTime(year.getTime() + (365 * 24 * 60 * 60 * 1000));
|
||||
var expires = '; expires=' + year.toGMTString();
|
||||
document.cookie = key + '=' + value + expires + '; path=/';
|
||||
};
|
||||
|
||||
Cookie.get = function (key) {
|
||||
key += '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var c = cookies[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1, c.length);
|
||||
}
|
||||
if (c.indexOf(key) == 0) {
|
||||
return c.substring(key.length, c.length);
|
||||
}
|
||||
export default class Cookie {
|
||||
// Thanks to http://www.quirksmode.org/js/cookies.html
|
||||
static set (key, value) {
|
||||
var year = new Date();
|
||||
year.setTime(year.getTime() + (365 * 24 * 60 * 60 * 1000));
|
||||
var expires = '; expires=' + year.toGMTString();
|
||||
document.cookie = key + '=' + value + expires + '; path=/';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
static get (key) {
|
||||
key += '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var c = cookies[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1, c.length);
|
||||
}
|
||||
if (c.indexOf(key) == 0) {
|
||||
return c.substring(key.length, c.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,95 +1,102 @@
|
|||
window.Localization = function () {};
|
||||
import Cookie from './Cookie';
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
let currentLocale;
|
||||
let root = '';
|
||||
let localizationMessages = {};
|
||||
let defaultLocalizationMessages = {};
|
||||
|
||||
// Configuration
|
||||
Localization.defaultLocale = Settings.defaultLocale;
|
||||
Localization.defaultLocaleShort = Settings.defaultLocaleShort;
|
||||
Localization.supportedLocales = Settings.supportedLocales;
|
||||
Localization.root = '';
|
||||
const defaultLocale = window.Settings.defaultLocale;
|
||||
const defaultLocaleShort = window.Settings.defaultLocaleShort;
|
||||
const supportedLocales = window.Settings.supportedLocales;
|
||||
const sampleKeyPrefix = 'key_';
|
||||
|
||||
// Take the browser's reported locale from navigator.language
|
||||
// Normalize this value and find a match in Localization.supportedLocales
|
||||
// If we support a similar language but not the specific one, it's returned.
|
||||
// E.g., if we support 'en-US' but not 'en-GB', the user gets 'en-US'
|
||||
// The match in supported locales (or the default locale) is returned.
|
||||
Localization.determineLocaleFromBrowser = function () {
|
||||
var localizationLanguage = window.navigator.userLanguage || window.navigator.language || 'en-us';
|
||||
export default class Localization {
|
||||
// Take the browser's reported locale from navigator.language
|
||||
// Normalize this value and find a match in supportedLocales
|
||||
// If we support a similar language but not the specific one, it's returned.
|
||||
// E.g., if we support 'en-US' but not 'en-GB', the user gets 'en-US'
|
||||
// The match in supported locales (or the default locale) is returned.
|
||||
static determineLocaleFromBrowser () {
|
||||
var localizationLanguage = window.navigator.userLanguage || window.navigator.language || 'en-us';
|
||||
|
||||
var localizationLanguageParts = localizationLanguage.split('-');
|
||||
// Capitalize last part of localization for includes
|
||||
localizationLanguageParts[localizationLanguageParts.length - 1] = (
|
||||
localizationLanguageParts[localizationLanguageParts.length - 1].toUpperCase()
|
||||
);
|
||||
var localizationLanguageParts = localizationLanguage.split('-');
|
||||
// Capitalize last part of localization for includes
|
||||
localizationLanguageParts[localizationLanguageParts.length - 1] = (
|
||||
localizationLanguageParts[localizationLanguageParts.length - 1].toUpperCase()
|
||||
);
|
||||
|
||||
var desiredLocale = localizationLanguageParts.join('-');
|
||||
if (desiredLocale in Object.keys(Localization.supportedLocales)) {
|
||||
return desiredLocale;
|
||||
}
|
||||
|
||||
// We're not supporting this locale yet - do we support an ancestor?
|
||||
for (var localeKey in Localization.supportedLocales) {
|
||||
var supportedLocale = Localization.supportedLocales[localeKey];
|
||||
var parts = supportedLocale.split('-');
|
||||
if (parts[0] == localizationLanguageParts[0]) {
|
||||
return supportedLocale; // Top-level is the same
|
||||
var desiredLocale = localizationLanguageParts.join('-');
|
||||
if (desiredLocale in Object.keys(supportedLocales)) {
|
||||
return desiredLocale;
|
||||
}
|
||||
|
||||
// We're not supporting this locale yet - do we support an ancestor?
|
||||
for (var localeKey in supportedLocales) {
|
||||
var supportedLocale = supportedLocales[localeKey];
|
||||
var parts = supportedLocale.split('-');
|
||||
if (parts[0] == localizationLanguageParts[0]) {
|
||||
return supportedLocale; // Top-level is the same
|
||||
}
|
||||
}
|
||||
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
return Localization.defaultLocale;
|
||||
};
|
||||
// Include locale support files and load the messages
|
||||
// Call this when the app is initialized
|
||||
static includeLocales () {
|
||||
var localizationCookie = Cookie.get('localization');
|
||||
if (localizationCookie === null) {
|
||||
currentLocale = this.determineLocaleFromBrowser();
|
||||
} else {
|
||||
currentLocale = localizationCookie;
|
||||
}
|
||||
// Intl locale-data
|
||||
document.write('<script src="' + root +
|
||||
'jssource/external/Intl/locale-data/jsonp/' + currentLocale + '.js"><\/script>');
|
||||
|
||||
// Include locale support files and load the messages
|
||||
// Call this when the app is initialized
|
||||
Localization.includeLocales = function () {
|
||||
var localizationCookie = Cookie.get('localization');
|
||||
if (localizationCookie === null) {
|
||||
Localization.currentLocale = Localization.determineLocaleFromBrowser();
|
||||
} else {
|
||||
Localization.currentLocale = localizationCookie;
|
||||
// MessageFormat locale-data
|
||||
var topLevel = currentLocale.split('-')[0];
|
||||
document.write('<script src="' + root +
|
||||
'jssource/external/intl-messageformat/locale-data/' + topLevel + '.js"><\/script>');
|
||||
|
||||
// Always load default locale
|
||||
document.write('<script src="' + root +
|
||||
'jssource/external/Intl/locale-data/jsonp/' + defaultLocale + '.js"><\/script>');
|
||||
document.write('<script src="' + root +
|
||||
'jssource/external/intl-messageformat/locale-data/' + defaultLocaleShort + '.js"><\/script>');
|
||||
|
||||
// Get messages synchronously
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', root + 'localizations/' + currentLocale + '.json', false);
|
||||
xhr.send(null);
|
||||
localizationMessages = JSON.parse(xhr.responseText);
|
||||
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', this.root + 'localizations/' + this.defaultLocale + '.json', false);
|
||||
xhr.send(null);
|
||||
defaultLocalizationMessages = JSON.parse(xhr.responseText);
|
||||
}
|
||||
// Intl locale-data
|
||||
document.write('<script src="' + Localization.root +
|
||||
'jssource/external/Intl/locale-data/jsonp/' + Localization.currentLocale + '.js"><\/script>');
|
||||
|
||||
// MessageFormat locale-data
|
||||
var topLevel = Localization.currentLocale.split('-')[0];
|
||||
document.write('<script src="' + Localization.root +
|
||||
'jssource/external/intl-messageformat/locale-data/' + topLevel + '.js"><\/script>');
|
||||
|
||||
// Always load default locale
|
||||
document.write('<script src="' + Localization.root +
|
||||
'jssource/external/Intl/locale-data/jsonp/' + Localization.defaultLocale + '.js"><\/script>');
|
||||
document.write('<script src="' + Localization.root +
|
||||
'jssource/external/intl-messageformat/locale-data/' + Localization.defaultLocaleShort + '.js"><\/script>');
|
||||
|
||||
// Get messages synchronously
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', Localization.root + 'localizations/' + Localization.currentLocale + '.json', false);
|
||||
xhr.send(null);
|
||||
Localization.localizationMessages = JSON.parse(xhr.responseText);
|
||||
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', Localization.root + 'localizations/' + Localization.defaultLocale + '.json', false);
|
||||
xhr.send(null);
|
||||
Localization.defaultLocalizationMessages = JSON.parse(xhr.responseText);
|
||||
};
|
||||
|
||||
// Translate a particular message given the message key and info
|
||||
Localization.localize = function (key, formatting) {
|
||||
var message;
|
||||
if (key in Localization.localizationMessages) {
|
||||
message = new IntlMessageFormat(Localization.localizationMessages[key], Localization.currentLocale);
|
||||
return message.format(formatting);
|
||||
} else if (key in Localization.defaultLocalizationMessages) {
|
||||
message = new IntlMessageFormat(Localization.defaultLocalizationMessages[key], Localization.defaultLocale);
|
||||
return message.format(formatting);
|
||||
// Translate a particular message given the message key and info
|
||||
static localize (key, formatting) {
|
||||
var message;
|
||||
if (key in localizationMessages) {
|
||||
message = new IntlMessageFormat(localizationMessages[key], currentLocale);
|
||||
return message.format(formatting);
|
||||
} else if (key in defaultLocalizationMessages) {
|
||||
message = new IntlMessageFormat(defaultLocalizationMessages[key], defaultLocale);
|
||||
return message.format(formatting);
|
||||
}
|
||||
return 'String missing: ' + key;
|
||||
}
|
||||
return 'String missing: ' + key;
|
||||
};
|
||||
|
||||
// For sample projects, some fields (sprite names, text on stage, and text in say blocks)
|
||||
// may have a special prefix to indicate that it should be replaced with a localized value.
|
||||
// E.g., we might have some text on the stage that says "Touch me" in English. This gets translated.
|
||||
Localization.sampleKeyPrefix = 'key_';
|
||||
Localization.isSampleLocalizedKey = function (str) {
|
||||
return str.slice(0, Localization.sampleKeyPrefix.length) == Localization.sampleKeyPrefix;
|
||||
};
|
||||
// For sample projects, some fields (sprite names, text on stage, and text in say blocks)
|
||||
// may have a special prefix to indicate that it should be replaced with a localized value.
|
||||
// E.g., we might have some text on the stage that says "Touch me" in English. This gets translated.
|
||||
static isSampleLocalizedKey (str) {
|
||||
return str.slice(0, sampleKeyPrefix.length) == sampleKeyPrefix;
|
||||
}
|
||||
}
|
||||
|
|
1270
src/utils/lib.js
1270
src/utils/lib.js
File diff suppressed because it is too large
Load diff
22
webpack.config.js
Normal file
22
webpack.config.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
module.exports = {
|
||||
entry: {
|
||||
index: './src/entry/index.js',
|
||||
editor: './src/entry/editor.js'
|
||||
},
|
||||
output: {
|
||||
path: './src/build/bundles',
|
||||
filename: '[name].bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
test: /\.jsx?$/,
|
||||
query: {
|
||||
presets: ['es2015']
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue