2015-05-01 09:32:37 -04:00
// Simulate the bare minimum of the view that exists on the main site
var Scratch = Scratch || { } ;
2017-03-15 14:17:48 -07:00
Scratch . editorIsReady = false ;
2015-05-01 09:32:37 -04:00
Scratch . FlashApp = Scratch . FlashApp || { } ;
2015-05-08 10:06:50 -04:00
var editorId = "scratch" ;
2015-05-09 14:57:18 -04:00
var initialPage = "home" ;
2015-05-09 14:29:40 -04:00
var ShortURL = {
2015-05-12 10:10:31 -04:00
key : "AIzaSyBlaftRUIOLFVs8nfrWvp4IBrqq9-az46A" ,
2015-05-09 14:29:40 -04:00
api : "https://www.googleapis.com/urlshortener/v1/url" ,
2018-05-01 19:22:12 -04:00
domain : "https://goo.gl"
2017-03-15 14:17:48 -07:00
} ;
2015-05-08 10:06:50 -04:00
2015-05-01 09:32:37 -04:00
function handleEmbedStatus ( e ) {
$ ( '#scratch-loader' ) . hide ( ) ;
2015-05-09 14:57:18 -04:00
var scratch = $ ( document . getElementById ( editorId ) ) ;
2015-05-01 09:32:37 -04:00
if ( ! e . success ) {
scratch . css ( 'marginTop' , '10' ) ;
scratch . find ( 'IMG.proj_thumb' ) . css ( 'width' , '179px' ) ;
scratch . find ( 'DIV.scratch_unsupported' ) . show ( ) ;
scratch . find ( 'DIV.scratch_loading' ) . hide ( ) ;
} else {
Scratch . FlashApp . ASobj = scratch [ 0 ] ;
2015-05-09 14:57:18 -04:00
Scratch . FlashApp . $ASobj = $ ( Scratch . FlashApp . ASobj ) ;
2015-05-01 09:32:37 -04:00
}
}
// enables the SWF to log errors
function JSthrowError ( e ) {
if ( window . onerror ) window . onerror ( e , 'swf' , 0 ) ;
else console . error ( e ) ;
}
function JSeditorReady ( ) {
try {
2017-03-15 14:17:48 -07:00
Scratch . editorIsReady = true ;
2015-05-14 14:08:36 -04:00
Scratch . FlashApp . $ASobj . trigger ( "editor:ready" ) ;
2015-05-01 09:32:37 -04:00
return true ;
} catch ( error ) {
console . error ( error . message , "\n" , error . stack ) ;
throw error ;
}
}
2015-05-07 17:06:35 -04:00
function JSshowExtensionDialog ( ) {
2015-08-05 16:13:10 -04:00
showModal ( [ "template-extension-file" , "template-extension-url" ] ) ;
2015-05-07 17:06:35 -04:00
}
2015-05-01 09:32:37 -04:00
var flashVars = {
autostart : 'false' ,
extensionDevMode : 'true' ,
server : encodeURIComponent ( location . host ) ,
cloudToken : '4af4863d-a921-4004-b2cb-e0ad00ee1927' ,
cdnToken : '34f16bc63e8ada7dfd7ec12c715d0c94' ,
urlOverrides : {
2018-05-01 19:22:12 -04:00
sitePrefix : "https://scratch.mit.edu/" ,
siteCdnPrefix : "https://cdn.scratch.mit.edu/" ,
assetPrefix : "https://assets.scratch.mit.edu/" ,
assetCdnPrefix : "https://cdn.assets.scratch.mit.edu/" ,
projectPrefix : "https://projects.scratch.mit.edu/" ,
projectCdnPrefix : "https://cdn.projects.scratch.mit.edu/" ,
2015-05-01 09:32:37 -04:00
internalAPI : "internalapi/" ,
siteAPI : "site-api/" ,
staticFiles : "scratchr2/static/"
} ,
inIE : ( navigator . userAgent . indexOf ( 'MSIE' ) > - 1 )
} ;
var params = {
allowscriptaccess : 'always' ,
allowfullscreen : 'true' ,
wmode : 'direct' ,
menu : 'false'
} ;
$ . each ( flashVars , function ( prop , val ) {
2017-01-04 13:56:12 -08:00
if ( $ . isPlainObject ( val ) ) {
val = encodeURIComponent ( JSON . stringify ( val ) ) ;
}
if ( typeof params . flashvars !== 'undefined' ) {
params . flashvars += '&' + prop + '=' + val ;
} else {
params . flashvars = prop + '=' + val ;
}
2015-05-01 09:32:37 -04:00
} ) ;
swfobject . switchOffAutoHideShow ( ) ;
2017-01-04 13:56:12 -08:00
var swfAttributes = {
data : 'Scratch.swf' ,
width : '100%' ,
height : '100%'
} ;
swfobject . addDomLoadEvent ( function ( ) {
// check if mobile/tablet browser user bowser
if ( bowser . mobile || bowser . tablet ) {
// if on mobile, show error screen
handleEmbedStatus ( { success : false } ) ;
} else {
// if not on ie, let browser try to handle flash loading
var swf = swfobject . createSWF ( swfAttributes , params , "scratch" ) ;
handleEmbedStatus ( { success : true , ref : swf } ) ;
}
} ) ;
2015-05-05 16:53:44 -04:00
2015-05-06 10:18:15 -04:00
/* File uploads */
2015-05-06 19:36:53 -04:00
function sendFileToFlash ( file ) {
2015-05-06 20:44:24 -04:00
/ *
* Use the HTML5 FileReader API to send base - 64 encoded file
* contents to Flash via ASloadBase64SBX ( or do it when the SWF
* is ready ) .
* /
2015-05-06 13:58:03 -04:00
var fileReader = new FileReader ( ) ;
2015-05-06 14:30:40 -04:00
fileReader . onload = function ( e ) {
var fileAsB64 = ab _to _b64 ( fileReader . result ) ;
if ( Scratch . FlashApp . ASobj . ASloadBase64SBX !== undefined ) {
2015-05-14 17:21:56 -04:00
$ ( document ) . trigger ( "editor:extensionLoaded" , { method : "file" } ) ;
2015-05-14 14:08:36 -04:00
showPage ( editorId ) ;
2015-05-06 14:30:40 -04:00
Scratch . FlashApp . ASobj . ASloadBase64SBX ( fileAsB64 ) ;
} else {
2015-05-14 14:08:36 -04:00
$ ( document ) . on ( "editor:ready" , function ( e ) {
2015-05-14 17:21:56 -04:00
$ ( document ) . trigger ( "editor:extensionLoaded" , { method : "file" } ) ;
2015-05-14 14:08:36 -04:00
showPage ( editorId ) ;
2015-05-06 14:30:40 -04:00
Scratch . FlashApp . ASobj . ASloadBase64SBX ( fileAsB64 ) ;
2015-05-06 20:17:43 -04:00
$ ( this ) . off ( e ) ;
} ) ;
2015-05-06 14:30:40 -04:00
}
2017-03-15 14:17:48 -07:00
} ;
2015-05-06 19:36:53 -04:00
fileReader . readAsArrayBuffer ( file ) ;
2015-05-06 10:18:15 -04:00
}
2015-05-08 20:07:05 -04:00
function sendURLtoFlash ( ) {
2015-05-06 20:44:24 -04:00
/ *
* Send a URL to Flash with ASloadGithubURL , or do it when the
* editor is ready .
* /
2015-05-08 20:48:53 -04:00
var urls = [ ] ;
for ( var i = 0 ; i < arguments . length ; i ++ ) {
urls . push ( arguments [ i ] ) ;
}
if ( urls . length <= 0 ) return ;
2017-03-15 14:17:48 -07:00
if ( Scratch . editorIsReady ) {
2015-05-14 17:21:56 -04:00
$ ( document ) . trigger ( "editor:extensionLoaded" , { method : "url" , urls : urls } ) ;
2015-05-15 10:10:18 -04:00
showPage ( editorId ) ;
2015-05-08 20:48:53 -04:00
Scratch . FlashApp . ASobj . ASloadGithubURL ( urls ) ;
2015-05-06 14:30:40 -04:00
} else {
2015-05-14 14:08:36 -04:00
$ ( document ) . on ( "editor:ready" , function ( e ) {
2015-05-14 17:21:56 -04:00
$ ( document ) . trigger ( "editor:extensionLoaded" , { method : "url" , urls : urls } ) ;
2015-05-15 10:10:18 -04:00
showPage ( editorId ) ;
2015-05-08 20:48:53 -04:00
Scratch . FlashApp . ASobj . ASloadGithubURL ( urls ) ;
2015-05-06 20:17:43 -04:00
$ ( this ) . off ( e ) ;
} ) ;
2015-05-06 14:30:40 -04:00
}
2015-05-06 10:18:15 -04:00
}
2015-05-06 20:44:24 -04:00
/* Load from URL */
2015-05-06 10:18:15 -04:00
2015-05-08 10:09:55 -04:00
function loadFromURLParameter ( queryString ) {
2015-05-06 20:44:24 -04:00
/ *
* Get all url = urlToLoad from the querystring and send to Flash
* Use like ...
* http : //scratchx.org/?url=urlToLoad1&url=urlToLoad2
* /
2015-05-08 10:09:55 -04:00
var paramString = queryString . replace ( /^\?|\/$/g , '' ) ;
2015-05-06 19:36:53 -04:00
var vars = paramString . split ( "&" ) ;
2015-05-08 20:07:05 -04:00
var urls = [ ] ;
2015-05-06 19:36:53 -04:00
for ( var i = 0 ; i < vars . length ; i ++ ) {
var pair = vars [ i ] . split ( "=" ) ;
if ( pair . length > 1 && pair [ 0 ] == "url" ) {
2015-05-08 20:07:05 -04:00
urls . push ( pair [ 1 ] ) ;
2015-05-06 19:36:53 -04:00
}
}
2015-05-08 20:07:05 -04:00
if ( urls . length > 0 ) sendURLtoFlash . apply ( window , urls ) ;
2015-05-06 19:36:53 -04:00
}
2015-05-07 17:06:35 -04:00
/* Modals */
2015-05-07 11:00:47 -04:00
2015-05-09 14:29:40 -04:00
function getOrCreateFromTemplate ( elementId , templateId , elementType , appendTo , wrapper , data ) {
elementType = elementType || "div" ;
appendTo = appendTo || "body" ;
data = data || { } ;
2015-05-09 14:57:18 -04:00
var $element = $ ( document . getElementById ( elementId ) ) ;
2015-05-07 11:00:47 -04:00
if ( ! $element . length ) {
2015-08-05 16:13:10 -04:00
var templateContent = "" ;
if ( typeof ( templateId ) != "string" ) {
for ( var id in templateId ) {
templateContent += $ ( document . getElementById ( templateId [ id ] ) ) . html ( ) ;
}
} else {
templateContent += $ ( document . getElementById ( templateId ) ) . html ( )
}
$template = _ . template ( templateContent ) ;
2015-05-07 17:06:35 -04:00
$element = $ ( "<" + elementType + "></" + elementType + ">" )
2015-05-07 11:00:47 -04:00
. attr ( "id" , elementId )
2015-05-09 14:29:40 -04:00
. html ( $template ( data ) ) ;
2015-05-07 17:06:35 -04:00
if ( wrapper ) $element . wrapInner ( wrapper ) ;
$element . appendTo ( appendTo )
2015-05-07 11:00:47 -04:00
}
return $element ;
2017-03-15 14:17:48 -07:00
}
2015-05-07 11:00:47 -04:00
2015-05-09 14:29:40 -04:00
function showModal ( templateId , data ) {
2015-05-07 11:00:47 -04:00
/ *
* Copies the HTML referenced by data - template into a new element ,
2015-05-07 17:06:35 -04:00
* with id = "modal-[template value]" and creates an overlay on the
2015-05-07 11:00:47 -04:00
* page , which when clicked will close the popup .
* /
var zIndex = 100 ;
2015-08-10 16:29:47 -04:00
var modalId = ( "modal-" + templateId ) . replace ( "," , "-" ) ;
2015-08-11 15:08:17 -04:00
$modalwrapper = $ ( "<div class='modal-fade-screen'><div class='modal-inner'></div></div>" ) ;
2015-05-09 14:29:40 -04:00
var $modal = getOrCreateFromTemplate ( modalId , templateId , "dialog" , "body" , $modalwrapper , data ) ;
2015-08-10 16:29:47 -04:00
2015-08-11 15:08:17 -04:00
$modal . addClass ( "modal" ) ;
2015-08-10 16:29:47 -04:00
2015-05-07 17:06:35 -04:00
$ ( ".modal-fade-screen" , $modal )
. addClass ( "visible" )
2015-05-14 14:08:36 -04:00
. click ( function ( e ) { if ( $ ( e . target ) . is ( $ ( this ) ) ) $ ( this ) . trigger ( "modal:exit" ) } ) ;
2015-08-10 16:29:47 -04:00
$ ( ".modal-close" , $modal ) . click ( function ( e ) {
e . preventDefault ( ) ;
$ ( document ) . trigger ( "modal:exit" )
} ) ;
2015-05-09 14:29:40 -04:00
2015-05-07 17:06:35 -04:00
$ ( "body" ) . addClass ( "modal-open" ) ;
2015-05-09 14:29:40 -04:00
2015-05-14 14:08:36 -04:00
$ ( document ) . one ( "modal:exit page:show editor:extensionLoaded" , function ( e ) {
2015-05-07 17:06:35 -04:00
$ ( "body" ) . removeClass ( "modal-open" ) ;
2015-11-25 13:23:13 -05:00
try {
Scratch . FlashApp . ASobj . ASsetModalOverlay ( false ) ;
} catch ( e ) {
// SWF not yet loaded
}
2015-05-09 14:29:40 -04:00
$modal . remove ( ) ;
2015-05-07 11:00:47 -04:00
} ) ;
2015-05-09 14:29:40 -04:00
2015-05-08 18:53:57 -04:00
return $modal ;
2015-05-07 17:06:35 -04:00
}
2015-05-08 10:09:16 -04:00
$ ( document ) . keyup ( function ( e ) {
// Exit modals with esc key
if ( e . keyCode == 27 ) $ ( document ) . trigger ( "modal:exit" ) ;
} ) ;
2015-11-25 13:23:13 -05:00
$ ( document ) . on ( "modal:exit" , function ( e ) {
try {
Scratch . FlashApp . ASobj . ASsetModalOverlay ( false ) ;
} catch ( e ) {
// SWF not yet loaded
}
} ) ;
2015-05-08 13:12:45 -04:00
2015-05-08 10:08:20 -04:00
$ ( document ) . on ( 'click' , "[data-action='modal']" , function ( e ) {
2015-05-07 17:06:35 -04:00
/ *
* Usage :
* < a href = "#content" data - action = "modal" data - template = "id-for-content" > Popup < / a >
* /
e . preventDefault ( ) ;
showModal ( $ ( this ) . data ( "template" ) ) ;
2015-05-07 11:00:47 -04:00
} ) ;
2015-05-08 18:53:57 -04:00
function JSshowWarning ( extensionData ) {
2015-05-14 14:08:36 -04:00
$modal = showModal ( "template-warning" , extensionData ) ;
2015-08-10 16:29:47 -04:00
$ ( "button" , $modal ) . click ( function ( e ) {
2015-05-08 18:53:57 -04:00
e . preventDefault ( ) ;
$ ( document ) . trigger ( "modal:exit" )
} ) ;
}
2015-05-07 11:00:47 -04:00
2015-05-06 10:17:51 -04:00
/* Page switching */
2015-05-12 10:09:03 -04:00
function showPage ( path , force ) {
2015-05-06 20:44:24 -04:00
/ *
2015-05-14 14:08:36 -04:00
Show a part of the page . The site is set up like
body
main
article # home
article # privacy - policy
...
editor
Each < article > is a "page" of the site , plus one special
view , which is the editor .
The editor is not actually hidden , but located - 9999 px above
the viewport . This is because if it 's hidden, it doesn' t load
when the page is loaded .
So first we have to hide everything that we ' re not going to show
or move the editor up , then display everything we ' re going to show
if it ' s hidden .
If we are linking to an anchor within a page , then show its parent .
* /
2015-05-06 15:06:32 -04:00
var toHide = "body > main, body > main > article" ;
2015-05-05 16:53:44 -04:00
var toShow = "#" + path ;
2015-05-06 15:06:32 -04:00
var $toShow = $ ( toShow ) ;
2015-05-12 10:09:03 -04:00
var showEditor = $toShow . is ( Scratch . FlashApp . $ASobj ) ;
var editorShown = parseInt ( Scratch . FlashApp . $ASobj . css ( "top" ) ) == 0 ;
2015-05-05 16:53:44 -04:00
2015-05-12 10:09:03 -04:00
if ( ! $toShow . length || ( ! showEditor && $toShow . filter ( ":visible" ) . length > 0 ) || ( showEditor && editorShown ) ) return ;
if ( editorShown && ! force ) {
Scratch . FlashApp . ASobj . AScreateNewProject ( [ "showPage" , path , true ] ) ;
return ;
}
2015-05-07 17:06:58 -04:00
2015-05-06 19:36:53 -04:00
$ ( toHide ) . filter ( ":visible" ) . hide ( ) ;
2015-05-12 10:09:03 -04:00
if ( ! showEditor && editorShown ) $ ( document . getElementById ( editorId ) ) . css ( { top : "-9999px" } ) ;
2015-05-06 15:06:32 -04:00
$ ( "body > main, body > main > article" ) . has ( $toShow ) . show ( ) ;
2015-08-06 14:39:44 -04:00
setBodyClass ( path ) ;
2015-05-06 15:06:32 -04:00
$toShow . show ( ) ;
2015-05-12 10:09:03 -04:00
if ( showEditor ) $toShow . css ( { top : 0 } ) ;
if ( document . location . hash . substr ( 1 ) != path ) document . location . hash = path ;
2015-05-13 14:02:05 -04:00
$toShow [ 0 ] . scrollIntoView ( true ) ;
2015-05-14 14:31:54 -04:00
$ ( document ) . trigger ( "page:show" , path ) ;
2015-05-05 16:53:44 -04:00
}
2015-08-06 14:39:44 -04:00
function setBodyClass ( path ) {
var pageClassPrefix = "page-" ;
var currentPageClasses = ( $ ( "body" ) . attr ( "class" ) || "" ) . split ( " " ) ;
for ( c in currentPageClasses ) {
if ( currentPageClasses [ c ] . indexOf ( pageClassPrefix ) != - 1 ) {
$ ( "body" ) . removeClass ( currentPageClasses [ c ] ) ;
}
}
$ ( "body" ) . addClass ( pageClassPrefix + path ) ;
}
2015-05-09 14:29:40 -04:00
/* URL Shortening */
function shorten ( url , done ) {
var data = { longUrl : url } ;
$ . ajax ( {
url : ShortURL . api + '?' + $ . param ( { key : ShortURL . key } ) ,
type : "post" ,
data : JSON . stringify ( data ) ,
dataType : "json" ,
contentType : "application/json"
} ) . done ( done ) ;
}
function getUrlFor ( extensions ) {
return document . location . origin + '/?' + $ . param (
extensions . map ( function ( url ) {
return { name : 'url' , value : url }
} )
) ;
}
function UrlParser ( url ) {
parser = document . createElement ( 'a' ) ;
parser . href = url ;
return parser
}
function showShortUrl ( url ) {
shorten ( url , function ( data ) {
var parser = UrlParser ( data . id ) ;
var id = parser . pathname . replace ( '/' , '' ) ;
parser . href = window . location . origin ;
parser . hash = "#!" + id ;
var shortUrl = parser . href ;
var context = {
longUrl : data . longUrl ,
shortUrl : shortUrl
2017-03-15 14:17:48 -07:00
} ;
2015-05-09 14:29:40 -04:00
$modal = showModal ( "template-short-url" , context ) ;
var client = new ZeroClipboard ( $ ( 'button' , $modal ) ) ;
} ) ;
}
function JSshowShortUrlFor ( ) {
showShortUrl ( getUrlFor ( Array . prototype . slice . call ( arguments ) ) ) ;
}
function decompress ( id , done ) {
2017-03-15 14:17:48 -07:00
var data = { shortUrl : ShortURL . domain + id } ;
2015-05-09 14:29:40 -04:00
$ . ajax ( {
url : ShortURL . api + '?' + $ . param ( {
key : ShortURL . key ,
shortUrl : ShortURL . domain + '/' + id } ) ,
dataType : "json" ,
contentType : "application/json"
} ) . done ( done ) ;
}
/* Setup */
2015-05-14 14:08:36 -04:00
$ ( document ) . on ( 'click' , "[data-action='load-file']" , function ( e ) {
/ *
Buttons with data - action = "load-file" trigger a file input
prompt , passed to a handler that passes the file to Flash .
* /
$ ( '<input type="file" />' ) . on ( 'change' , function ( ) {
sendFileToFlash ( this . files [ 0 ] )
} ) . click ( ) ;
} ) ;
$ ( document ) . on ( 'click' , "[data-action='load-url']" , function ( e ) {
/ *
Links with data - action = "load-url" send their href to Flash
So use like ...
< a href = "?url=urlToLoad" data - action = "load-url" > Load this < / a >
* /
e . preventDefault ( ) ;
showPage ( editorId ) ;
loadFromURLParameter ( $ ( this ) . attr ( "href" ) ) ;
} ) ;
$ ( document ) . on ( 'submit' , ".url-load-form" , function ( e ) {
// Load text input value on submit
2017-03-15 14:17:48 -07:00
e . preventDefault ( ) ;
2015-05-14 14:08:36 -04:00
showPage ( editorId ) ;
sendURLtoFlash ( $ ( 'input[type="text"]' , this ) . val ( ) ) ;
} ) ;
$ ( document ) . on ( 'click' , "[data-action='show']" , function ( e ) {
/ *
Links with data - action = "static-link" should switch the view
to that page . Works like tabs sort of . Use like ...
<!-- Makes a link to the Privacy Policy section -- >
< a href = "#privacy-policy" data - action = "static-link" > Privacy Policy < / a >
* /
var path = $ ( this ) . data ( 'target' ) || $ ( this ) . attr ( "href" ) . substring ( 1 ) ;
showPage ( path ) ;
} ) ;
2015-05-13 14:02:05 -04:00
$ ( window ) . on ( 'hashchange' , function ( e ) {
var path = document . location . hash . split ( '#' ) [ 1 ] || document . location . hash || 'home' ;
2015-05-15 10:09:58 -04:00
if ( path . charAt ( 0 ) != '!' ) showPage ( path ) ;
2015-05-13 14:02:05 -04:00
} ) ;
2015-05-14 17:21:19 -04:00
$ ( document ) . on ( "page:show" , function ( e , page ) {
2015-05-15 09:52:35 -04:00
ga ( "send" , "pageview" , '#' + page ) ;
2015-05-14 17:21:19 -04:00
ga ( "set" , "referrer" , document . location . origin + document . location . pathname + document . location . hash )
} ) ;
2015-05-14 17:21:56 -04:00
$ ( document ) . on ( "editor:extensionLoaded" , function ( e , data ) {
if ( data . method == "url" ) {
for ( var i = 0 ; url = data [ 'urls' ] [ i ] ; i ++ ) {
ga ( "send" , "event" , "extensionLoaded" , data . method , url ) ;
}
} else {
ga ( "send" , "event" , "extensionLoaded" , data . method ) ;
}
} ) ;
2015-05-06 09:53:59 -04:00
function initPage ( ) {
2015-05-06 20:44:24 -04:00
/ *
2015-05-14 14:08:36 -04:00
On load , show the page identified by the URL fragment . Default to # home .
* /
2015-05-09 14:29:40 -04:00
if ( window . location . hash ) {
if ( window . location . hash . charAt ( 1 ) == "!" ) {
decompress ( window . location . hash . substr ( 2 ) , function ( data ) {
var parser = UrlParser ( data . longUrl ) ;
if ( parser . hostname == window . location . hostname ) window . location = data . longUrl ;
return ;
} ) ;
} else {
2015-05-09 14:57:18 -04:00
initialPage = window . location . hash . substr ( 1 ) ;
2015-05-09 14:29:40 -04:00
}
}
2015-08-06 14:39:44 -04:00
setBodyClass ( initialPage ) ;
2015-05-14 14:21:08 -04:00
showPage ( initialPage , true ) ;
2015-05-12 10:09:03 -04:00
loadFromURLParameter ( window . location . search , true ) ;
2015-05-06 09:53:59 -04:00
}
$ ( initPage ) ;