diff --git a/.eslintrc b/.eslintrc index 6085c08..00cda1c 100644 --- a/.eslintrc +++ b/.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, diff --git a/editions/free/src/editor.html b/editions/free/src/editor.html index da2270d..74c991d 100644 --- a/editions/free/src/editor.html +++ b/editions/free/src/editor.html @@ -11,23 +11,13 @@ - @@ -91,23 +81,8 @@ - - - +
diff --git a/editions/free/src/index.html b/editions/free/src/index.html index e1f7982..e509e63 100644 --- a/editions/free/src/index.html +++ b/editions/free/src/index.html @@ -10,24 +10,20 @@ ScratchJr Intro - - + + + - + - - + - -
-
-
-
-
- -
-
-
-
-
-
- + +
+
+
+
+
+ +
+
+
+
+
+
diff --git a/package.json b/package.json index 1a7b83d..52fb660 100644 --- a/package.json +++ b/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" + } } diff --git a/src/build/bundles/editor.bundle.js b/src/build/bundles/editor.bundle.js new file mode 100644 index 0000000..5b03563 --- /dev/null +++ b/src/build/bundles/editor.bundle.js @@ -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('\n'); + document.write('\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; + }; + +/***/ } +/******/ ]); \ No newline at end of file diff --git a/src/build/bundles/index.bundle.js b/src/build/bundles/index.bundle.js new file mode 100644 index 0000000..db1e5d4 --- /dev/null +++ b/src/build/bundles/index.bundle.js @@ -0,0 +1,3068 @@ +/******/ (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 _Localization = __webpack_require__(2); + + var _Localization2 = _interopRequireDefault(_Localization); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function startup() { + ScratchAudio.init(); + var urlvars = _lib.Lib.getUrlVars(); + if (urlvars.back) { + loadOptions(); + } else { + firstTime(); + } + setTimeout(function () { + _lib.Lib.gn('rays').className = 'rays spinme'; + }, 250); + } + + function firstTime() { + _lib.Lib.gn('authors').className = 'credits show'; + _lib.Lib.gn('authorsText').className = 'creditsText show'; + _lib.Lib.gn('purpleguy').className = 'purple show'; + _lib.Lib.gn('blueguy').className = 'blue show'; + _lib.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.Lib.gn('authors').className = 'credits hide'; + _lib.Lib.gn('authorsText').className = 'creditsText hide'; + _lib.Lib.gn('purpleguy').className = 'purple hide'; + _lib.Lib.gn('blueguy').className = 'blue hide'; + _lib.Lib.gn('redguy').className = 'red hide'; + _lib.Lib.gn('gettings').className = 'gettings show'; + _lib.Lib.gn('startcode').className = 'startcode show'; + document.ontouchmove = function (e) { + e.preventDefault(); + }; + if (_lib.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 (_lib.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 = function () { + _Localization2.default.includeLocales(); + _lib.Lib.preprocessAndLoadCss('css', 'css/font.css'); + _lib.Lib.preprocessAndLoadCss('css', 'css/base.css'); + _lib.Lib.preprocessAndLoadCss('css', 'css/start.css'); + _lib.Lib.preprocessAndLoadCss('css', 'css/thumbs.css'); + _lib.Lib.gn('gettings').ontouchend = gettingstarted; + _lib.Lib.gn('startcode').ontouchend = gohome; + + iOS.waitForInterface(startup); + }; + +/***/ }, +/* 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('\n'); + document.write('\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; + }; + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + '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 + }); + + var _Cookie = __webpack_require__(3); + + var _Cookie2 = _interopRequireDefault(_Cookie); + + var _intlMessageformat = __webpack_require__(4); + + var _intlMessageformat2 = _interopRequireDefault(_intlMessageformat); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var currentLocale = undefined; + var root = ''; + var localizationMessages = {}; + var defaultLocalizationMessages = {}; + + // Configuration + var defaultLocale = window.Settings.defaultLocale; + var defaultLocaleShort = window.Settings.defaultLocaleShort; + var supportedLocales = window.Settings.supportedLocales; + var sampleKeyPrefix = 'key_'; + + var Localization = function () { + function Localization() { + _classCallCheck(this, Localization); + } + + _createClass(Localization, null, [{ + key: 'determineLocaleFromBrowser', + + // 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. + value: function 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 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; + } + + // Include locale support files and load the messages + // Call this when the app is initialized + + }, { + key: 'includeLocales', + value: function includeLocales() { + var localizationCookie = _Cookie2.default.get('localization'); + if (localizationCookie === null) { + currentLocale = this.determineLocaleFromBrowser(); + } else { + currentLocale = localizationCookie; + } + // Intl locale-data + document.write('